diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/examples/TestClient.java b/jetty-websocket/websocket-client/src/test/java/examples/ClientDemo.java similarity index 94% rename from jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/examples/TestClient.java rename to jetty-websocket/websocket-client/src/test/java/examples/ClientDemo.java index def25cf9134..063197c8112 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/examples/TestClient.java +++ b/jetty-websocket/websocket-client/src/test/java/examples/ClientDemo.java @@ -16,7 +16,7 @@ // ======================================================================== // -package org.eclipse.jetty.websocket.client.examples; +package examples; import java.net.InetSocketAddress; import java.net.URI; @@ -37,9 +37,12 @@ import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule; /** - * This is not a general purpose websocket client. It's only for testing the websocket server and is hardwired to a specific draft version of the protocol. + * This is not a general purpose websocket client. + *

+ * It's only for testing the websocket server and is hardwired to a specific draft version of the protocol. + *

*/ -public class TestClient +public class ClientDemo { public class TestSocket extends WebSocketAdapter { @@ -96,7 +99,7 @@ public class TestClient private static final Random __random = new Random(); - private static LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("TestClient"); + private static LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("ClientDemo"); private final String _host; private final int _port; @@ -174,7 +177,7 @@ public class TestClient } } - TestClient[] client = new TestClient[clients]; + ClientDemo[] client = new ClientDemo[clients]; WebSocketClient wsclient = new WebSocketClient(bufferPool); try { @@ -184,7 +187,7 @@ public class TestClient for (int i = 0; i < clients; i++) { - client[i] = new TestClient(wsclient,host,port,protocol,60000); + client[i] = new ClientDemo(wsclient,host,port,protocol,60000); client[i].open(); } @@ -259,7 +262,7 @@ public class TestClient private static void usage(String[] args) { System.err.println("ERROR: " + Arrays.asList(args)); - System.err.println("USAGE: java -cp CLASSPATH " + TestClient.class + " [ OPTIONS ]"); + System.err.println("USAGE: java -cp CLASSPATH " + ClientDemo.class + " [ OPTIONS ]"); System.err.println(" -h|--host HOST (default localhost)"); System.err.println(" -p|--port PORT (default 8080)"); System.err.println(" -b|--binary"); @@ -281,7 +284,7 @@ public class TestClient private WebSocketClient client; private TestSocket socket; - public TestClient(WebSocketClient client, String host, int port, String protocol, int timeoutMS) throws Exception + public ClientDemo(WebSocketClient client, String host, int port, String protocol, int timeoutMS) throws Exception { this.client = client; _host = host; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ClosePayloadParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ClosePayloadParserTest.java deleted file mode 100644 index 86c51c75e9f..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ClosePayloadParserTest.java +++ /dev/null @@ -1,65 +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; - -import static org.hamcrest.Matchers.is; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; - -import org.eclipse.jetty.websocket.api.StatusCode; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.test.ParserCapture; -import org.eclipse.jetty.websocket.common.test.UnitParser; -import org.eclipse.jetty.websocket.common.util.MaskedByteBuffer; -import org.junit.Assert; -import org.junit.Test; - -public class ClosePayloadParserTest -{ - @Test - public void testGameOver() - { - String expectedReason = "Game Over"; - - byte utf[] = expectedReason.getBytes(StandardCharsets.UTF_8); - ByteBuffer payload = ByteBuffer.allocate(utf.length + 2); - payload.putChar((char)StatusCode.NORMAL); - payload.put(utf,0,utf.length); - payload.flip(); // to read - - ByteBuffer buf = ByteBuffer.allocate(24); - buf.put((byte)(0x80 | OpCode.CLOSE)); // fin + close - buf.put((byte)(0x80 | payload.remaining())); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,payload); - buf.flip(); // to read - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.CLOSE,1); - CloseInfo close = new CloseInfo(capture.getFrames().poll()); - Assert.assertThat("CloseFrame.statusCode",close.getStatusCode(),is(StatusCode.NORMAL)); - Assert.assertThat("CloseFrame.data",close.getReason(),is(expectedReason)); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase3.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorFrameFlagsTest.java similarity index 53% rename from jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase3.java rename to jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorFrameFlagsTest.java index 339d759ced1..e503651426b 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase3.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorFrameFlagsTest.java @@ -16,20 +16,16 @@ // ======================================================================== // -package org.eclipse.jetty.websocket.common.ab; +package org.eclipse.jetty.websocket.common; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.websocket.api.ProtocolException; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.PingFrame; import org.eclipse.jetty.websocket.common.frames.PongFrame; import org.eclipse.jetty.websocket.common.test.UnitGenerator; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -39,51 +35,34 @@ import org.junit.runners.Parameterized.Parameters; * Test various invalid frame situations */ @RunWith(value = Parameterized.class) -public class TestABCase3 +public class GeneratorFrameFlagsTest { @Parameters public static Collection data() { List data = new ArrayList<>(); - // @formatter:off - data.add(new WebSocketFrame[] - { new PingFrame().setFin(false) }); - data.add(new WebSocketFrame[] - { new PingFrame().setRsv1(true) }); - data.add(new WebSocketFrame[] - { new PingFrame().setRsv2(true) }); - data.add(new WebSocketFrame[] - { new PingFrame().setRsv3(true) }); - data.add(new WebSocketFrame[] - { new PongFrame().setFin(false) }); - data.add(new WebSocketFrame[] - { new PingFrame().setRsv1(true) }); - data.add(new WebSocketFrame[] - { new PongFrame().setRsv2(true) }); - data.add(new WebSocketFrame[] - { new PongFrame().setRsv3(true) }); - data.add(new WebSocketFrame[] - { new CloseInfo().asFrame().setFin(false) }); - data.add(new WebSocketFrame[] - { new CloseInfo().asFrame().setRsv1(true) }); - data.add(new WebSocketFrame[] - { new CloseInfo().asFrame().setRsv2(true) }); - data.add(new WebSocketFrame[] - { new CloseInfo().asFrame().setRsv3(true) }); - // @formatter:on + data.add(new WebSocketFrame[]{new PingFrame().setFin(false)}); + data.add(new WebSocketFrame[]{new PingFrame().setRsv1(true)}); + data.add(new WebSocketFrame[]{new PingFrame().setRsv2(true)}); + data.add(new WebSocketFrame[]{new PingFrame().setRsv3(true)}); + data.add(new WebSocketFrame[]{new PongFrame().setFin(false)}); + data.add(new WebSocketFrame[]{new PingFrame().setRsv1(true)}); + data.add(new WebSocketFrame[]{new PongFrame().setRsv2(true)}); + data.add(new WebSocketFrame[]{new PongFrame().setRsv3(true)}); + data.add(new WebSocketFrame[]{new CloseInfo().asFrame().setFin(false)}); + data.add(new WebSocketFrame[]{new CloseInfo().asFrame().setRsv1(true)}); + data.add(new WebSocketFrame[]{new CloseInfo().asFrame().setRsv2(true)}); + data.add(new WebSocketFrame[]{new CloseInfo().asFrame().setRsv3(true)}); return data; } - - @Rule - public TestTracker tt = new TestTracker(); - + private WebSocketFrame invalidFrame; - - public TestABCase3(WebSocketFrame invalidFrame) + + public GeneratorFrameFlagsTest(WebSocketFrame invalidFrame) { this.invalidFrame = invalidFrame; } - + @Test(expected = ProtocolException.class) public void testGenerateInvalidControlFrame() { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java index d61a5913ce4..878318ee99e 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/GeneratorTest.java @@ -21,123 +21,349 @@ package org.eclipse.jetty.websocket.common; import static org.hamcrest.Matchers.is; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Arrays; 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.ProtocolException; import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.frames.BinaryFrame; import org.eclipse.jetty.websocket.common.frames.CloseFrame; +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.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; +import org.junit.rules.ExpectedException; public class GeneratorTest { private static final Logger LOG = Log.getLogger(GeneratorTest.WindowHelper.class); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); - public static class WindowHelper + /** + * From Autobahn WebSocket Client Testcase 1.2.2 + *

+ * (generates a payload-length using 1 bytes) + *

+ */ + @Test + public void testGenerate_Binary_125BytePayload() { - final int windowSize; - int totalParts; - int totalBytes; - - public WindowHelper(int windowSize) + int length = 125; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) { - this.windowSize = windowSize; - this.totalParts = 0; - this.totalBytes = 0; + bb.put("*".getBytes()); } - - public ByteBuffer generateWindowed(Frame... frames) + + bb.flip(); + + WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); + + ByteBuffer actual = UnitGenerator.generate(binaryFrame); + + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= length & 0x7F; + expected.put(b); + + for ( int i = 0 ; i < length ; ++i ) { - // Create Buffer to hold all generated frames in a single buffer - int completeBufSize = 0; - for (Frame f : frames) - { - completeBufSize += Generator.MAX_HEADER_LENGTH + f.getPayloadLength(); - } - - ByteBuffer completeBuf = ByteBuffer.allocate(completeBufSize); - BufferUtil.clearToFill(completeBuf); - - // Generate from all frames - Generator generator = new UnitGenerator(); - - for (Frame f : frames) - { - ByteBuffer header = generator.generateHeaderBytes(f); - totalBytes += BufferUtil.put(header,completeBuf); - - if (f.hasPayload()) - { - ByteBuffer payload=f.getPayload(); - totalBytes += payload.remaining(); - totalParts++; - completeBuf.put(payload.slice()); - } - } - - // Return results - BufferUtil.flipToFlush(completeBuf,0); - return completeBuf; - } - - public void assertTotalParts(int expectedParts) - { - Assert.assertThat("Generated Parts",totalParts,is(expectedParts)); - } - - public void assertTotalBytes(int expectedBytes) - { - Assert.assertThat("Generated Bytes",totalBytes,is(expectedBytes)); + expected.put("*".getBytes()); } + + BufferUtil.flipToFlush(expected,0); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); } - private void assertGeneratedBytes(CharSequence expectedBytes, Frame... frames) + /** + * From Autobahn WebSocket Client Testcase 1.2.3 + *

+ * (generates a payload-length using 2 bytes) + *

+ */ + @Test + public void testGenerate_Binary_126BytePayload() { - // collect up all frames as single ByteBuffer - ByteBuffer allframes = UnitGenerator.generate(frames); - // Get hex String form of all frames bytebuffer. - String actual = Hex.asHex(allframes); - // Validate - Assert.assertThat("Buffer",actual,is(expectedBytes.toString())); - } - - private String asMaskedHex(String str, byte[] maskingKey) - { - byte utf[] = StringUtil.getUtf8Bytes(str); - mask(utf,maskingKey); - return Hex.asHex(utf); - } - - private void mask(byte[] buf, byte[] maskingKey) - { - int size = buf.length; - for (int i = 0; i < size; i++) + int length = 126; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) { - buf[i] ^= maskingKey[i % 4]; + bb.put("*".getBytes()); } + + bb.flip(); + + WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); + + ByteBuffer actual = UnitGenerator.generate(binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + + expected.putShort((short)length); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + BufferUtil.flipToFlush(expected,0); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.2.4 + *

+ * (generates a payload-length using 2 bytes) + *

+ */ + @Test + public void testGenerate_Binary_127BytePayload() + { + int length = 127; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + + WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); + + ByteBuffer actual = UnitGenerator.generate(binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + + expected.putShort((short)length); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + BufferUtil.flipToFlush(expected,0); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.2.5 + *

+ * (generates a payload-length using 2 bytes) + *

+ */ + @Test + public void testGenerate_Binary_128BytePayload() + { + int length = 128; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); + + ByteBuffer actual = UnitGenerator.generate(binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + + expected.put((byte)(length>>8)); + expected.put((byte)(length & 0xFF)); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + BufferUtil.flipToFlush(expected,0); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + + } + + /** + * From Autobahn WebSocket Client Testcase 1.2.6 + *

+ * (generates a payload-length using 2 bytes) + *

+ */ + @Test + public void testGenerate_Binary_65535BytePayload() + { + int length = 65535; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + + WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); + + ByteBuffer actual = UnitGenerator.generate(binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.put(new byte[]{ (byte)0xff, (byte)0xff}); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + BufferUtil.flipToFlush(expected,0); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.2.7 + *

+ * (generates a payload-length using 8 bytes) + *

+ */ + @Test + public void testGenerate_Binary_65536BytePayload() + { + int length = 65536; + + ByteBuffer bb = ByteBuffer.allocate(length); + + for ( int i = 0 ; i < length ; ++i) + { + bb.put("*".getBytes()); + + } + + bb.flip(); + + WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); + + ByteBuffer actual = UnitGenerator.generate(binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 11); + + expected.put(new byte[] + { (byte)0x82 }); + + byte b = 0x00; // no masking + b |= 0x7F; + expected.put(b); + expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); + + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + BufferUtil.flipToFlush(expected,0); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.2.1 + */ + @Test + public void testGenerate_Binary_Empty() + { + WebSocketFrame binaryFrame = new BinaryFrame().setPayload(new byte[] {}); + + ByteBuffer actual = UnitGenerator.generate(binaryFrame); + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x82, (byte)0x00 }); + + BufferUtil.flipToFlush(expected,0); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 7.3.2 + */ + @Test + public void testGenerate_Close_1BytePayload() + { + CloseFrame closeFrame = new CloseFrame(); + closeFrame.setPayload(Hex.asByteBuffer("00")); + + expectedException.expect(ProtocolException.class); + UnitGenerator.generate(closeFrame); } @Test - public void testClose_Empty() - { - // 0 byte payload (no status code) - assertGeneratedBytes("8800",new CloseFrame()); - } - - @Test - public void testClose_CodeNoReason() + public void testGenerate_Close_CodeNoReason() { CloseInfo close = new CloseInfo(StatusCode.NORMAL); // 2 byte payload (2 bytes for status code) @@ -145,68 +371,138 @@ public class GeneratorTest } @Test - public void testClose_CodeOkReason() + public void testGenerate_Close_CodeOkReason() { CloseInfo close = new CloseInfo(StatusCode.NORMAL,"OK"); // 4 byte payload (2 bytes for status code, 2 more for "OK") assertGeneratedBytes("880403E84F4B",close.asFrame()); } + /** + * From Autobahn WebSocket Client Testcase 7.3.1 + */ @Test - public void testText_Hello() + public void testGenerate_Close_Empty() { - WebSocketFrame frame = new TextFrame().setPayload("Hello"); - byte utf[] = StringUtil.getUtf8Bytes("Hello"); - assertGeneratedBytes("8105" + Hex.asHex(utf),frame); + // 0 byte payload (no status code) + assertGeneratedBytes("8800",new CloseFrame()); } + /** + * From Autobahn WebSocket Client Testcase 7.3.6 + */ @Test - public void testText_Masked() + public void testGenerate_Close_WithInvalidStatusReason() { - WebSocketFrame frame = new TextFrame().setPayload("Hello"); - byte maskingKey[] = Hex.asByteArray("11223344"); - frame.setMask(maskingKey); - - // what is expected - StringBuilder expected = new StringBuilder(); - expected.append("8185").append("11223344"); - expected.append(asMaskedHex("Hello",maskingKey)); - - // validate - assertGeneratedBytes(expected,frame); + StringBuilder message = new StringBuilder(); + for ( int i = 0 ; i < 124 ; ++i ) + { + message.append("*"); + } + + byte[] messageBytes = message.toString().getBytes(); + + CloseFrame closeFrame = new CloseFrame(); + + ByteBuffer bb = ByteBuffer.allocate(CloseFrame.MAX_CONTROL_PAYLOAD + 1); // 126 which is too big for control + + bb.putChar((char)1000); + bb.put(messageBytes); + + BufferUtil.flipToFlush(bb,0); + + expectedException.expect(ProtocolException.class); + closeFrame.setPayload(bb); } - + + /** + * From Autobahn WebSocket Client Testcase 7.3.3 + */ @Test - public void testText_Masked_OffsetSourceByteBuffer() + public void testGenerate_Close_WithStatus() { - ByteBuffer payload = ByteBuffer.allocate(100); - payload.position(5); - payload.put(StringUtil.getUtf8Bytes("Hello")); - payload.flip(); - payload.position(5); - // at this point, we have a ByteBuffer of 100 bytes. - // but only a few bytes in the middle are made available for the payload. - // we are testing that masking works as intended, even if the provided - // payload does not start at position 0. - LOG.debug("Payload = {}",BufferUtil.toDetailString(payload)); - WebSocketFrame frame = new TextFrame().setPayload(payload); - byte maskingKey[] = Hex.asByteArray("11223344"); - frame.setMask(maskingKey); - - // what is expected - StringBuilder expected = new StringBuilder(); - expected.append("8185").append("11223344"); - expected.append(asMaskedHex("Hello",maskingKey)); - - // validate - assertGeneratedBytes(expected,frame); + CloseInfo close = new CloseInfo(1000); + + ByteBuffer actual = UnitGenerator.generate(close.asFrame()); + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 }); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); } - + + /** + * From Autobahn WebSocket Client Testcase 7.3.5 + */ + @Test + public void testGenerate_Close_WithStatusMaxReason() + { + StringBuilder message = new StringBuilder(); + for ( int i = 0 ; i < 123 ; ++i ) + { + message.append("*"); + } + + CloseInfo close = new CloseInfo(1000,message.toString()); + + ByteBuffer actual = UnitGenerator.generate(close.asFrame()); + ByteBuffer expected = ByteBuffer.allocate(132); + + byte messageBytes[] = message.toString().getBytes(StandardCharsets.UTF_8); + + expected.put(new byte[] + { (byte)0x88 }); + + byte b = 0x00; // no masking + b |= (messageBytes.length + 2) & 0x7F; + expected.put(b); + expected.putShort((short)1000); + + expected.put(messageBytes); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 7.3.4 + */ + @Test + public void testGenerate_Close_WithStatusReason() + { + String message = "bad cough"; + byte[] messageBytes = message.getBytes(); + + CloseInfo close = new CloseInfo(1000,message); + + ByteBuffer actual = UnitGenerator.generate(close.asFrame()); + + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] + { (byte)0x88 }); + + byte b = 0x00; // no masking + b |= (message.length() + 2) & 0x7F; + expected.put(b); + expected.putShort((short)1000); + expected.put(messageBytes); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + /** * Prevent regression of masking of many packets. */ @Test - public void testManyMasked() + public void testGenerate_Masked_ManyFrames() { int pingCount = 2; @@ -238,12 +534,650 @@ public class GeneratorTest assertGeneratedBytes(expected,frames); } + + /** + * From Autobahn WebSocket Client Testcase 2.4 + */ + @Test + public void testGenerate_Ping_125BytePayload() + { + byte[] bytes = new byte[125]; + + for ( int i = 0 ; i < bytes.length ; ++i ) + { + bytes[i] = Integer.valueOf(Integer.toOctalString(i)).byteValue(); + } + + WebSocketFrame pingFrame = new PingFrame().setPayload(bytes); + + ByteBuffer actual = UnitGenerator.generate(pingFrame); + + ByteBuffer expected = ByteBuffer.allocate(bytes.length + 32); + + expected.put(new byte[] + { (byte)0x89 }); + + byte b = 0x00; // no masking + b |= bytes.length & 0x7F; + expected.put(b); + expected.put(bytes); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 2.3 + */ + @Test + public void testGenerate_Ping_BinaryPaylod() + { + byte[] bytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + + PingFrame pingFrame = new PingFrame().setPayload(bytes); + + ByteBuffer actual = UnitGenerator.generate(pingFrame); + + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] + { (byte)0x89 }); + + byte b = 0x00; // no masking + b |= bytes.length & 0x7F; + expected.put(b); + expected.put(bytes); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 2.1 + */ + @Test + public void testGenerate_Ping_Empty() + { + WebSocketFrame pingFrame = new PingFrame(); + + ByteBuffer actual = UnitGenerator.generate(pingFrame); + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x89, (byte)0x00 }); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 2.2 + */ + @Test + public void testGenerate_Ping_HelloPayload() + { + String message = "Hello, world!"; + byte[] messageBytes = StringUtil.getUtf8Bytes(message); + + PingFrame pingFrame = new PingFrame().setPayload(messageBytes); + + ByteBuffer actual = UnitGenerator.generate(pingFrame); + + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] + { (byte)0x89 }); + + byte b = 0x00; // no masking + b |= messageBytes.length & 0x7F; + expected.put(b); + expected.put(messageBytes); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 2.5 + */ + @Test + public void testGenerate_Ping_OverSizedPayload() + { + byte[] bytes = new byte[126]; + Arrays.fill(bytes,(byte)0x00); + + expectedException.expect(WebSocketException.class); + PingFrame pingFrame = new PingFrame(); + pingFrame.setPayload(ByteBuffer.wrap(bytes)); // should throw exception + } + + /** + * From Autobahn WebSocket Client Testcase 2.5 + */ + @Test + public void testGenerate_Pong_OverSizedPayload() + { + byte[] bytes = new byte[126]; + Arrays.fill(bytes, (byte)0x00); + + expectedException.expect(WebSocketException.class); + PongFrame pingFrame = new PongFrame(); + pingFrame.setPayload(ByteBuffer.wrap(bytes)); // should throw exception + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testGenerate_RFC6455_FragmentedUnmaskedTextMessage() + { + WebSocketFrame text1 = new TextFrame().setPayload("Hel").setFin(false); + WebSocketFrame text2 = new ContinuationFrame().setPayload("lo"); + + ByteBuffer actual1 = UnitGenerator.generate(text1); + ByteBuffer actual2 = UnitGenerator.generate(text2); + + ByteBuffer expected1 = ByteBuffer.allocate(5); + + expected1.put(new byte[] + { (byte)0x01, (byte)0x03, (byte)0x48, (byte)0x65, (byte)0x6c }); + + ByteBuffer expected2 = ByteBuffer.allocate(4); + + expected2.put(new byte[] + { (byte)0x80, (byte)0x02, (byte)0x6c, (byte)0x6f }); + + expected1.flip(); + expected2.flip(); + + ByteBufferAssert.assertEquals("t1 buffers are not equal",expected1,actual1); + ByteBufferAssert.assertEquals("t2 buffers are not equal",expected2,actual2); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testGenerate_RFC6455_SingleMaskedPongRequest() + { + PongFrame pong = new PongFrame().setPayload("Hello"); + pong.setMask(new byte[] + { 0x37, (byte)0xfa, 0x21, 0x3d }); + + ByteBuffer actual = UnitGenerator.generate(pong); + + ByteBuffer expected = ByteBuffer.allocate(11); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // Unmasked Pong request + expected.put(new byte[] + { (byte)0x8a, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); + expected.flip(); // make readable + + ByteBufferAssert.assertEquals("pong buffers are not equal",expected,actual); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testGenerate_RFC6455_SingleMaskedTextMessage() + { + WebSocketFrame text = new TextFrame().setPayload("Hello"); + text.setMask(new byte[] + { 0x37, (byte)0xfa, 0x21, 0x3d }); + + ByteBuffer actual = UnitGenerator.generate(text); + + ByteBuffer expected = ByteBuffer.allocate(11); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // A single-frame masked text message + expected.put(new byte[] + { (byte)0x81, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); + expected.flip(); // make readable + + ByteBufferAssert.assertEquals("masked text buffers are not equal",expected,actual); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testGenerate_RFC6455_SingleUnmasked256ByteBinaryMessage() + { + int dataSize = 256; + + BinaryFrame binary = new BinaryFrame(); + byte payload[] = new byte[dataSize]; + Arrays.fill(payload,(byte)0x44); + binary.setPayload(ByteBuffer.wrap(payload)); + + ByteBuffer actual = UnitGenerator.generate(binary); + + ByteBuffer expected = ByteBuffer.allocate(dataSize + Generator.MAX_HEADER_LENGTH); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // 256 bytes binary message in a single unmasked frame + expected.put(new byte[] + { (byte)0x82, (byte)0x7E }); + expected.putShort((short)0x01_00); + + for (int i = 0; i < dataSize; i++) + { + expected.put((byte)0x44); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("binary buffers are not equal",expected,actual); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testGenerate_RFC6455_SingleUnmasked64KBinaryMessage() + { + int dataSize = 1024 * 64; + + BinaryFrame binary = new BinaryFrame(); + byte payload[] = new byte[dataSize]; + Arrays.fill(payload,(byte)0x44); + binary.setPayload(ByteBuffer.wrap(payload)); + + ByteBuffer actual = UnitGenerator.generate(binary); + + ByteBuffer expected = ByteBuffer.allocate(dataSize + 10); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // 64k bytes binary message in a single unmasked frame + expected.put(new byte[] + { (byte)0x82, (byte)0x7F }); + expected.putInt(0x00_00_00_00); + expected.putInt(0x00_01_00_00); + + for (int i = 0; i < dataSize; i++) + { + expected.put((byte)0x44); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("binary buffers are not equal",expected,actual); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testGenerate_RFC6455_SingleUnmaskedPingRequest() throws Exception + { + PingFrame ping = new PingFrame().setPayload("Hello"); + + ByteBuffer actual = UnitGenerator.generate(ping); + + ByteBuffer expected = ByteBuffer.allocate(10); + expected.put(new byte[] + { (byte)0x89, (byte)0x05, (byte)0x48, (byte)0x65, (byte)0x6c, (byte)0x6c, (byte)0x6f }); + expected.flip(); // make readable + + ByteBufferAssert.assertEquals("Ping buffers",expected,actual); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testGenerate_RFC6455_SingleUnmaskedTextMessage() + { + WebSocketFrame text = new TextFrame().setPayload("Hello"); + + ByteBuffer actual = UnitGenerator.generate(text); + + ByteBuffer expected = ByteBuffer.allocate(10); + + expected.put(new byte[] + { (byte)0x81, (byte)0x05, (byte)0x48, (byte)0x65, (byte)0x6c, (byte)0x6c, (byte)0x6f }); + + expected.flip(); + + ByteBufferAssert.assertEquals("t1 buffers are not equal",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.1.2 + */ + @Test + public void testGenerate_Text_125BytePaylod() + { + int length = 125; + byte buf[] = new byte[length]; + Arrays.fill(buf,(byte)'*'); + String text = new String(buf, StandardCharsets.UTF_8); + + Frame textFrame = new TextFrame().setPayload(text); + + ByteBuffer actual = UnitGenerator.generate(textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= length & 0x7F; + expected.put(b); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.1.3 + */ + @Test + public void testGenerate_Text_126BytePaylod() + { + int length = 126; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); + + ByteBuffer actual = UnitGenerator.generate(textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + + expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.1.4 + */ + @Test + public void testGenerate_Text_127BytePayload() + { + int length = 127; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); + + ByteBuffer actual = UnitGenerator.generate(textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + + expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.1.5 + */ + @Test + public void testGenerate_Text_128BytePayload() + { + int length = 128; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); + + ByteBuffer actual = UnitGenerator.generate(textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + + expected.put((byte)(length >> 8)); + expected.put((byte)(length & 0xFF)); + // expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.1.6 + */ + @Test + public void testGenerate_Text_65535BytePayload() + { + int length = 65535; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); + + ByteBuffer actual = UnitGenerator.generate(textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.put(new byte[] + { (byte)0xff, (byte)0xff }); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.1.7 + */ + @Test + public void testGenerate_Text_65536BytePayload() + { + int length = 65536; + + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; ++i) + { + builder.append("*"); + } + + WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); + + ByteBuffer actual = UnitGenerator.generate(textFrame); + + ByteBuffer expected = ByteBuffer.allocate(length + 11); + + expected.put(new byte[] + { (byte)0x81 }); + + byte b = 0x00; // no masking + b |= 0x7F; + expected.put(b); + expected.put(new byte[] + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + /** + * From Autobahn WebSocket Client Testcase 1.1.1 + */ + @Test + public void testGenerate_Text_Empty() + { + WebSocketFrame textFrame = new TextFrame().setPayload(""); + + ByteBuffer actual = UnitGenerator.generate(textFrame); + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x81, (byte)0x00 }); + + expected.flip(); + + ByteBufferAssert.assertEquals("buffers do not match",expected,actual); + } + + @Test + public void testGenerate_Text_Hello() + { + WebSocketFrame frame = new TextFrame().setPayload("Hello"); + byte utf[] = StringUtil.getUtf8Bytes("Hello"); + assertGeneratedBytes("8105" + Hex.asHex(utf),frame); + } + + @Test + public void testGenerate_Text_Masked() + { + WebSocketFrame frame = new TextFrame().setPayload("Hello"); + byte maskingKey[] = Hex.asByteArray("11223344"); + frame.setMask(maskingKey); + // what is expected + StringBuilder expected = new StringBuilder(); + expected.append("8185").append("11223344"); + expected.append(asMaskedHex("Hello",maskingKey)); + + // validate + assertGeneratedBytes(expected,frame); + } + + @Test + public void testGenerate_Text_Masked_OffsetSourceByteBuffer() + { + ByteBuffer payload = ByteBuffer.allocate(100); + payload.position(5); + payload.put(StringUtil.getUtf8Bytes("Hello")); + payload.flip(); + payload.position(5); + // at this point, we have a ByteBuffer of 100 bytes. + // but only a few bytes in the middle are made available for the payload. + // we are testing that masking works as intended, even if the provided + // payload does not start at position 0. + LOG.debug("Payload = {}",BufferUtil.toDetailString(payload)); + WebSocketFrame frame = new TextFrame().setPayload(payload); + byte maskingKey[] = Hex.asByteArray("11223344"); + frame.setMask(maskingKey); + + // what is expected + StringBuilder expected = new StringBuilder(); + expected.append("8185").append("11223344"); + expected.append(asMaskedHex("Hello",maskingKey)); + + // validate + assertGeneratedBytes(expected,frame); + } + /** * Test the windowed generate of a frame that has no masking. */ @Test - public void testWindowedGenerate() + public void testGenerate_Windowed() { // A decent sized frame, no masking byte payload[] = new byte[10240]; @@ -266,9 +1200,12 @@ public class GeneratorTest Assert.assertThat("Generated Buffer",completeBuffer.remaining(),is(expectedSize)); } - + + /** + * This is to prevent a regression in the masking of many frames. + */ @Test - public void testWindowedGenerateWithMasking() + public void testGenerate_WindowedWithMasking() { // A decent sized frame, with masking byte payload[] = new byte[10240]; @@ -315,4 +1252,88 @@ public class GeneratorTest Assert.assertThat("Actual.payload[" + actualData.position() + "]",actualData.get(),is((byte)0x55)); } } + + public static class WindowHelper + { + final int windowSize; + int totalParts; + int totalBytes; + + public WindowHelper(int windowSize) + { + this.windowSize = windowSize; + this.totalParts = 0; + this.totalBytes = 0; + } + + public void assertTotalBytes(int expectedBytes) + { + Assert.assertThat("Generated Bytes",totalBytes,is(expectedBytes)); + } + + public void assertTotalParts(int expectedParts) + { + Assert.assertThat("Generated Parts",totalParts,is(expectedParts)); + } + + public ByteBuffer generateWindowed(Frame... frames) + { + // Create Buffer to hold all generated frames in a single buffer + int completeBufSize = 0; + for (Frame f : frames) + { + completeBufSize += Generator.MAX_HEADER_LENGTH + f.getPayloadLength(); + } + + ByteBuffer completeBuf = ByteBuffer.allocate(completeBufSize); + BufferUtil.clearToFill(completeBuf); + + // Generate from all frames + Generator generator = new UnitGenerator(); + + for (Frame f : frames) + { + ByteBuffer header = generator.generateHeaderBytes(f); + totalBytes += BufferUtil.put(header,completeBuf); + + if (f.hasPayload()) + { + ByteBuffer payload=f.getPayload(); + totalBytes += payload.remaining(); + totalParts++; + completeBuf.put(payload.slice()); + } + } + + // Return results + BufferUtil.flipToFlush(completeBuf,0); + return completeBuf; + } + } + + private void assertGeneratedBytes(CharSequence expectedBytes, Frame... frames) + { + // collect up all frames as single ByteBuffer + ByteBuffer allframes = UnitGenerator.generate(frames); + // Get hex String form of all frames bytebuffer. + String actual = Hex.asHex(allframes); + // Validate + Assert.assertThat("Buffer",actual,is(expectedBytes.toString())); + } + + private String asMaskedHex(String str, byte[] maskingKey) + { + byte utf[] = StringUtil.getUtf8Bytes(str); + mask(utf,maskingKey); + return Hex.asHex(utf); + } + + private void mask(byte[] buf, byte[] maskingKey) + { + int size = buf.length; + for (int i = 0; i < size; i++) + { + buf[i] ^= maskingKey[i % 4]; + } + } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java index 27c6905973b..d1c7e5dd1c6 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ParserTest.java @@ -18,19 +18,27 @@ package org.eclipse.jetty.websocket.common; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; import static org.junit.Assert.assertThat; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.websocket.api.MessageTooLargeException; import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; import org.eclipse.jetty.websocket.common.frames.DataFrame; import org.eclipse.jetty.websocket.common.frames.PingFrame; @@ -40,6 +48,9 @@ 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; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -50,10 +61,428 @@ public class ParserTest public ExpectedException expectedException = ExpectedException.none(); /** - * Similar to the server side 5.15 testcase. A normal 2 fragment text text message, followed by another continuation. + * From Autobahn WebSocket Server Testcase 1.2.2 */ @Test - public void testParseCase5_15() + public void testParse_Binary_125BytePayload() + { + int length = 125; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + byte b = 0x00; // no masking + b |= length & 0x7F; + expected.put(b); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); + // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); + } + + /** + * From Autobahn WebSocket Server Testcase 1.2.3 + */ + @Test + public void testParse_Binary_126BytePayload() + { + int length = 126; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + expected.putShort((short)length); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); + // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); + } + + /** + * From Autobahn WebSocket Server Testcase 1.2.4 + */ + @Test + public void testParse_Binary_127BytePayload() + { + int length = 127; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + expected.putShort((short)length); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); + // .assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); + } + + /** + * From Autobahn WebSocket Server Testcase 1.2.5 + */ + @Test + public void testParse_Binary_128BytePayload() + { + int length = 128; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.putShort((short)length); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); + } + + /** + * From Autobahn WebSocket Server Testcase 1.2.6 + */ + @Test + public void testParse_Binary_65535BytePayload() + { + int length = 65535; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x82 }); + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.put(new byte[]{ (byte)0xff, (byte)0xff}); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + expected.flip(); + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + policy.setMaxBinaryMessageSize(length); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); + } + + /** + * From Autobahn WebSocket Server Testcase 1.2.7 + */ + @Test + public void testParse_Binary_65536BytePayload() + { + int length = 65536; + + ByteBuffer expected = ByteBuffer.allocate(length + 11); + + expected.put(new byte[] + { (byte)0x82 }); + byte b = 0x00; // no masking + b |= 0x7F; + expected.put(b); + expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); + + for ( int i = 0 ; i < length ; ++i ) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + policy.setMaxBinaryMessageSize(length); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); + } + + /** + * From Autobahn WebSocket Server Testcase 1.2.1 + */ + @Test + public void testParse_Binary_Empty() + { + + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x82, (byte)0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0)); + } + + /** + * From Autobahn WebSocket Server Testcase 7.3.2 + */ + @Test + public void testParse_Close_1BytePayload() + { + ByteBuffer expected = Hex.asByteBuffer("880100"); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(CoreMatchers.containsString("Invalid close frame payload length")); + parser.parse(expected); + } + + /** + * From Autobahn WebSocket Server Testcase 7.3.1 + */ + @Test + public void testParse_Close_Empty() + { + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x88, (byte)0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.CLOSE,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0)); + } + + /** + * From Autobahn WebSocket Server Testcase 7.4.6 + */ + @Test + public void testParse_Close_WithInvalidStatusReason() + { + byte[] messageBytes = new byte[124]; + Arrays.fill(messageBytes,(byte)'*'); + + ByteBuffer expected = ByteBuffer.allocate(256); + + byte b; + + // fin + op + b = 0x00; + b |= 0x80; // fin on + b |= 0x08; // close + expected.put(b); + + // mask + len + b = 0x00; + b |= 0x00; // no masking + b |= 0x7E; // 2 byte len + expected.put(b); + + // 2 byte len + expected.putChar((char)(messageBytes.length + 2)); + + // payload + expected.putShort((short)1000); // status code + expected.put(messageBytes); // reason + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(CoreMatchers.containsString("Invalid control frame payload length")); + parser.parse(expected); + } + + /** + * From Autobahn WebSocket Server Testcase 7.3.3 + */ + @Test + public void testParse_Close_WithStatus() + { + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.CLOSE,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2)); + } + + /** + * From Autobahn WebSocket Server Testcase 7.3.5 + */ + @Test + public void testParse_Close_WithStatusMaxReason() + { + StringBuilder message = new StringBuilder(); + for ( int i = 0 ; i < 123 ; ++i ) + { + message.append("*"); + } + + byte[] messageBytes = message.toString().getBytes(StandardCharsets.UTF_8); + + ByteBuffer expected = ByteBuffer.allocate(132); + + expected.put(new byte[] + { (byte)0x88 }); + byte b = 0x00; // no masking + + b |= (messageBytes.length + 2) & 0x7F; + expected.put(b); + expected.putShort((short)1000); + + expected.put(messageBytes); + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.CLOSE,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125)); + } + + /** + * From Autobahn WebSocket Server Testcase 7.3.4 + */ + @Test + public void testParse_Close_WithStatusReason() + { + String message = "bad cough"; + byte[] messageBytes = message.getBytes(); + + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] + { (byte)0x88 }); + byte b = 0x00; // no masking + b |= (messageBytes.length + 2) & 0x7F; + expected.put(b); + expected.putShort((short)1000); // status code + expected.put(messageBytes); // status reason + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.CLOSE,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2)); + } + + /** + * From Autobahn WebSocket Server Testcase 5.15 + *

+ * A normal 2 fragment text text message, followed by another continuation. + *

+ */ + @Test + public void testParse_Continuation_BadFinState() { List send = new ArrayList<>(); send.add(new TextFrame().setPayload("fragment1").setFin(false)); @@ -68,85 +497,16 @@ public class ParserTest expectedException.expect(ProtocolException.class); parser.parse(completeBuf); - - capture.assertHasFrame(OpCode.TEXT,1); - capture.assertHasFrame(OpCode.CONTINUATION,1); } - + /** - * Similar to the server side 5.18 testcase. Text message fragmented as 2 frames, both as opcode=TEXT + * From Autobahn WebSocket Server Testcase 6.2.3 + *

+ * Lots of small 1 byte UTF8 Text frames, representing 1 overall text message. + *

*/ @Test - public void testParseCase5_18() - { - List send = new ArrayList<>(); - send.add(new TextFrame().setPayload("fragment1").setFin(false)); - send.add(new TextFrame().setPayload("fragment2").setFin(true)); // bad frame, must be continuation - send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); - - ByteBuffer completeBuf = UnitGenerator.generate(send); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); - - expectedException.expect(ProtocolException.class); - parser.parse(completeBuf); - - capture.assertHasFrame(OpCode.TEXT,1); // fragment 1 - } - - /** - * Similar to the server side 5.19 testcase. text message, send in 5 frames/fragments, with 2 pings in the mix. - */ - @Test - public void testParseCase5_19() - { - List send = new ArrayList<>(); - send.add(new TextFrame().setPayload("f1").setFin(false)); - send.add(new ContinuationFrame().setPayload(",f2").setFin(false)); - send.add(new PingFrame().setPayload("pong-1")); - send.add(new ContinuationFrame().setPayload(",f3").setFin(false)); - send.add(new ContinuationFrame().setPayload(",f4").setFin(false)); - send.add(new PingFrame().setPayload("pong-2")); - send.add(new ContinuationFrame().setPayload(",f5").setFin(true)); - send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); - - ByteBuffer completeBuf = UnitGenerator.generate(send); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); - parser.parse(completeBuf); - - capture.assertHasFrame(OpCode.TEXT,1); - capture.assertHasFrame(OpCode.CONTINUATION,4); - capture.assertHasFrame(OpCode.CLOSE,1); - capture.assertHasFrame(OpCode.PING,2); - } - - /** - * Similar to the server side 5.6 testcase. pong, then text, then close frames. - */ - @Test - public void testParseCase5_6() - { - List send = new ArrayList<>(); - send.add(new PongFrame().setPayload("ping")); - send.add(new TextFrame().setPayload("hello, world")); - send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); - - ByteBuffer completeBuf = UnitGenerator.generate(send); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); - parser.parse(completeBuf); - - capture.assertHasFrame(OpCode.TEXT,1); - capture.assertHasFrame(OpCode.CLOSE,1); - capture.assertHasFrame(OpCode.PONG,1); - } - - /** - * Similar to the server side 6.2.3 testcase. Lots of small 1 byte UTF8 Text frames, representing 1 overall text message. - */ - @Test - public void testParseCase6_2_3() + public void testParse_Continuation_ManySmall() { String utf8 = "Hello-\uC2B5@\uC39F\uC3A4\uC3BC\uC3A0\uC3A1-UTF-8!!"; byte msg[] = StringUtil.getUtf8Bytes(utf8); @@ -189,9 +549,39 @@ public class ParserTest capture.assertHasFrame(OpCode.CONTINUATION,continuationCount); capture.assertHasFrame(OpCode.CLOSE,1); } - + + /** + * From Autobahn WebSocket Server Testcase 5.19 + *

+ * text message, send in 5 frames/fragments, with 2 pings in the mix. + *

+ */ @Test - public void testParseNothing() + public void testParse_Interleaved_PingFrames() + { + List send = new ArrayList<>(); + send.add(new TextFrame().setPayload("f1").setFin(false)); + send.add(new ContinuationFrame().setPayload(",f2").setFin(false)); + send.add(new PingFrame().setPayload("ping-1")); + send.add(new ContinuationFrame().setPayload(",f3").setFin(false)); + send.add(new ContinuationFrame().setPayload(",f4").setFin(false)); + send.add(new PingFrame().setPayload("ping-2")); + send.add(new ContinuationFrame().setPayload(",f5").setFin(true)); + send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); + + ByteBuffer completeBuf = UnitGenerator.generate(send); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); + parser.parse(completeBuf); + + capture.assertHasFrame(OpCode.TEXT,1); + capture.assertHasFrame(OpCode.CONTINUATION,4); + capture.assertHasFrame(OpCode.CLOSE,1); + capture.assertHasFrame(OpCode.PING,2); + } + + @Test + public void testParse_Nothing() { ByteBuffer buf = ByteBuffer.allocate(16); // Put nothing in the buffer. @@ -205,9 +595,915 @@ public class ParserTest assertThat("Frame Count",capture.getFrames().size(),is(0)); } - + + /** + * From Autobahn WebSocket Server Testcase 4.2.1 + */ @Test - public void testWindowedParseLargeFrame() + public void testParse_OpCode11() throws Exception + { + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] { (byte)0x8b, 0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 11")); + parser.parse(expected); + } + + /** + * From Autobahn WebSocket Server Testcase 4.2.2 + */ + @Test + public void testParse_OpCode12() throws Exception + { + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] { (byte)0x8c, 0x01, 0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy, capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 12")); + parser.parse(expected); + } + + /** + * From Autobahn WebSocket Server Testcase 4.1.1 + */ + @Test + public void testParse_OpCode3() throws Exception + { + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] { (byte)0x83, 0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy, capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 3")); + parser.parse(expected); + } + + /** + * From Autobahn WebSocket Server Testcase 4.1.2 + */ + @Test + public void testParse_OpCode4() throws Exception + { + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] { (byte)0x84, 0x01, 0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + expectedException.expectMessage(containsString("Unknown opcode: 4")); + parser.parse(expected); + } + + /** + * From Autobahn WebSocket Server Testcase 2.4 + */ + @Test + public void testParse_Ping_125BytePayload() + { + byte[] bytes = new byte[125]; + + for ( int i = 0 ; i < bytes.length ; ++i ) + { + bytes[i] = Integer.valueOf(Integer.toOctalString(i)).byteValue(); + } + + ByteBuffer expected = ByteBuffer.allocate(bytes.length + 32); + + expected.put(new byte[] + { (byte)0x89 }); + + byte b = 0x00; // no masking + b |= bytes.length & 0x7F; + expected.put(b); + expected.put(bytes); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.PING,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length)); + Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); + } + + @Test + public void testParse_Ping_Basic() + { + ByteBuffer buf = ByteBuffer.allocate(16); + BufferUtil.clearToFill(buf); + buf.put(new byte[] + { (byte)0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); + BufferUtil.flipToFlush(buf,0); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.PING,1); + PingFrame ping = (PingFrame)capture.getFrames().poll(); + + String actual = BufferUtil.toUTF8String(ping.getPayload()); + Assert.assertThat("PingFrame.payload",actual,is("Hello")); + } + + /** + * From Autobahn WebSocket Server Testcase 2.3 + */ + @Test + public void testParse_Ping_BinaryPayload() + { + byte[] bytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] + { (byte)0x89 }); + + byte b = 0x00; // no masking + b |= bytes.length & 0x7F; + expected.put(b); + expected.put(bytes); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.PING,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length)); + Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); + } + + /** + * From Autobahn WebSocket Server Testcase 2.1 + */ + @Test + public void testParse_Ping_Empty() + { + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x89, (byte)0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.PING,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(0)); + Assert.assertEquals("PingFrame.payload",0,pActual.getPayloadLength()); + } + + /** + * From Autobahn WebSocket Server Testcase 2.2 + */ + @Test + public void testParse_Ping_HelloPayload() + { + String message = "Hello, world!"; + byte[] messageBytes = message.getBytes(); + + ByteBuffer expected = ByteBuffer.allocate(32); + + expected.put(new byte[] + { (byte)0x89 }); + + byte b = 0x00; // no masking + b |= messageBytes.length & 0x7F; + expected.put(b); + expected.put(messageBytes); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.PING,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(message.length())); + Assert.assertEquals("PingFrame.payload",message.length(),pActual.getPayloadLength()); + } + + /** + * From Autobahn WebSocket Server Testcase 2.5 + */ + @Test + public void testParse_Ping_OverSizedPayload() + { + byte[] bytes = new byte[126]; + Arrays.fill(bytes,(byte)0x00); + + ByteBuffer expected = ByteBuffer.allocate(bytes.length + Generator.MAX_HEADER_LENGTH); + + byte b; + + // fin + op + b = 0x00; + b |= 0x80; // fin on + b |= 0x09; // ping + expected.put(b); + + // mask + len + b = 0x00; + b |= 0x00; // no masking + b |= 0x7E; // 2 byte len + expected.put(b); + + // 2 byte len + expected.putChar((char)bytes.length); + + // payload + expected.put(bytes); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + parser.parse(expected); + } + + /** + * From Autobahn WebSocket Server Testcase 5.6 + *

+ * pong, then text, then close frames. + *

+ */ + @Test + public void testParse_PongTextClose() + { + List send = new ArrayList<>(); + send.add(new PongFrame().setPayload("ping")); + send.add(new TextFrame().setPayload("hello, world")); + send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); + + ByteBuffer completeBuf = UnitGenerator.generate(send); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); + parser.parse(completeBuf); + + capture.assertHasFrame(OpCode.TEXT,1); + capture.assertHasFrame(OpCode.CLOSE,1); + capture.assertHasFrame(OpCode.PONG,1); + } + + /** + * From Autobahn WebSocket Server Testcase 2.5 + */ + @Test + public void testParse_Pong_OverSizedPayload() + { + byte[] bytes = new byte[126]; + Arrays.fill(bytes,(byte)0x00); + + ByteBuffer expected = ByteBuffer.allocate(bytes.length + Generator.MAX_HEADER_LENGTH); + + byte b; + + // fin + op + b = 0x00; + b |= 0x80; // fin on + b |= 0x0A; // pong + expected.put(b); + + // mask + len + b = 0x00; + b |= 0x00; // no masking + b |= 0x7E; // 2 byte len + expected.put(b); + + // 2 byte len + expected.putChar((char)bytes.length); + + // payload + expected.put(bytes); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(ProtocolException.class); + parser.parse(expected); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testParse_RFC6455_FragmentedUnmaskedTextMessage() + { + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + + ByteBuffer buf = ByteBuffer.allocate(16); + BufferUtil.clearToFill(buf); + + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // A fragmented unmasked text message (part 1 of 2 "Hel") + buf.put(new byte[] + { (byte)0x01, (byte)0x03, 0x48, (byte)0x65, 0x6c }); + + // Parse #1 + BufferUtil.flipToFlush(buf,0); + parser.parse(buf); + + // part 2 of 2 "lo" (A continuation frame of the prior text message) + BufferUtil.flipToFill(buf); + buf.put(new byte[] + { (byte)0x80, 0x02, 0x6c, 0x6f }); + + // Parse #2 + BufferUtil.flipToFlush(buf,0); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + capture.assertHasFrame(OpCode.CONTINUATION,1); + + WebSocketFrame txt = capture.getFrames().poll(); + String actual = BufferUtil.toUTF8String(txt.getPayload()); + assertThat("TextFrame[0].data",actual,is("Hel")); + txt = capture.getFrames().poll(); + actual = BufferUtil.toUTF8String(txt.getPayload()); + assertThat("TextFrame[1].data",actual,is("lo")); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testParse_RFC6455_SingleMaskedPongRequest() + { + ByteBuffer buf = ByteBuffer.allocate(16); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // Unmasked Pong request + buf.put(new byte[] + { (byte)0x8a, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.PONG,1); + + WebSocketFrame pong = capture.getFrames().poll(); + String actual = BufferUtil.toUTF8String(pong.getPayload()); + assertThat("PongFrame.payload",actual,is("Hello")); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testParse_RFC6455_SingleMaskedTextMessage() + { + ByteBuffer buf = ByteBuffer.allocate(16); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // A single-frame masked text message + buf.put(new byte[] + { (byte)0x81, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + + WebSocketFrame txt = capture.getFrames().poll(); + String actual = BufferUtil.toUTF8String(txt.getPayload()); + assertThat("TextFrame.payload",actual,is("Hello")); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testParse_RFC6455_SingleUnmasked256ByteBinaryMessage() + { + int dataSize = 256; + + ByteBuffer buf = ByteBuffer.allocate(dataSize + 10); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // 256 bytes binary message in a single unmasked frame + buf.put(new byte[] + { (byte)0x82, 0x7E }); + buf.putShort((short)0x01_00); // 16 bit size + for (int i = 0; i < dataSize; i++) + { + buf.put((byte)0x44); + } + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame bin = capture.getFrames().poll(); + + assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize)); + + ByteBuffer data = bin.getPayload(); + assertThat("BinaryFrame.payload.length",data.remaining(),is(dataSize)); + + for (int i = 0; i < dataSize; i++) + { + assertThat("BinaryFrame.payload[" + i + "]",data.get(i),is((byte)0x44)); + } + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testParse_RFC6455_SingleUnmasked64KByteBinaryMessage() + { + int dataSize = 1024 * 64; + + ByteBuffer buf = ByteBuffer.allocate((dataSize + 10)); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // 64 Kbytes binary message in a single unmasked frame + buf.put(new byte[] + { (byte)0x82, 0x7F }); + buf.putLong(dataSize); // 64bit size + for (int i = 0; i < dataSize; i++) + { + buf.put((byte)0x77); + } + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + assertThat(parser.parse(buf), is(true)); + + capture.assertHasFrame(OpCode.BINARY,1); + + Frame bin = capture.getFrames().poll(); + + assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize)); + ByteBuffer data = bin.getPayload(); + assertThat("BinaryFrame.payload.length",data.remaining(),is(dataSize)); + + for (int i = 0; i < dataSize; i++) + { + assertThat("BinaryFrame.payload[" + i + "]",data.get(i),is((byte)0x77)); + } + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testParse_RFC6455_SingleUnmaskedPingRequest() + { + ByteBuffer buf = ByteBuffer.allocate(16); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // Unmasked Ping request + buf.put(new byte[] + { (byte)0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.PING,1); + + WebSocketFrame ping = capture.getFrames().poll(); + String actual = BufferUtil.toUTF8String(ping.getPayload()); + assertThat("PingFrame.payload",actual,is("Hello")); + } + + /** + * Example from RFC6455 Spec itself. + *

+ * See RFC 6455 Examples section + *

+ */ + @Test + public void testParse_RFC6455_SingleUnmaskedTextMessage() + { + ByteBuffer buf = ByteBuffer.allocate(16); + // Raw bytes as found in RFC 6455, Section 5.7 - Examples + // A single-frame unmasked text message + buf.put(new byte[] + { (byte)0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + + WebSocketFrame txt = capture.getFrames().poll(); + String actual = BufferUtil.toUTF8String(txt.getPayload()); + assertThat("TextFrame.payload",actual,is("Hello")); + } + + /** + * From Autobahn WebSocket Server Testcase 1.1.2 + */ + @Test + public void testParse_Text_125BytePayload() + { + int length = 125; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + byte b = 0x00; // no masking + b |= length & 0x7F; + expected.put(b); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.TEXT,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); + } + + /** + * From Autobahn WebSocket Server Testcase 1.1.3 + */ + @Test + public void testParse_Text_126BytePayload() + { + int length = 126; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.TEXT,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); + } + + /** + * From Autobahn WebSocket Server Testcase 1.1.4 + */ + @Test + public void testParse_Text_127BytePaylod() + { + int length = 127; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + byte b = 0x00; // no masking + b |= length & 0x7E; + expected.put(b); + expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.TEXT,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); + } + + /** + * From Autobahn WebSocket Server Testcase 1.1.5 + */ + @Test + public void testParse_Text_128BytePayload() + { + int length = 128; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.putShort((short)length); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.TEXT,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + // .assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); + } + + /** + * From Autobahn WebSocket Server Testcase 1.1.6 + */ + @Test + public void testParse_Text_65535BytePayload() + { + int length = 65535; + + ByteBuffer expected = ByteBuffer.allocate(length + 5); + + expected.put(new byte[] + { (byte)0x81 }); + byte b = 0x00; // no masking + b |= 0x7E; + expected.put(b); + expected.put(new byte[] + { (byte)0xff, (byte)0xff }); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + policy.setMaxTextMessageSize(length); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.TEXT,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + } + + /** + * From Autobahn WebSocket Server Testcase 1.1.7 + */ + @Test + public void testParse_Text_65536BytePayload() + { + int length = 65536; + + ByteBuffer expected = ByteBuffer.allocate(length + 11); + + expected.put(new byte[] + { (byte)0x81 }); + byte b = 0x00; // no masking + b |= 0x7F; + expected.put(b); + expected.put(new byte[] + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }); + + for (int i = 0; i < length; ++i) + { + expected.put("*".getBytes()); + } + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + policy.setMaxTextMessageSize(length); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.TEXT,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); + } + + /** + * From Autobahn WebSocket Server Testcase 5.18 + *

+ * Text message fragmented as 2 frames, both as opcode=TEXT + *

+ */ + @Test + public void testParse_Text_BadFinState() + { + List send = new ArrayList<>(); + send.add(new TextFrame().setPayload("fragment1").setFin(false)); + send.add(new TextFrame().setPayload("fragment2").setFin(true)); // bad frame, must be continuation + send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); + + ByteBuffer completeBuf = UnitGenerator.generate(send); + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(WebSocketPolicy.newServerPolicy(),capture); + + expectedException.expect(ProtocolException.class); + parser.parse(completeBuf); + } + + /** + * From Autobahn WebSocket Server Testcase 1.1.1 + */ + @Test + public void testParse_Text_Empty() + { + ByteBuffer expected = ByteBuffer.allocate(5); + + expected.put(new byte[] + { (byte)0x81, (byte)0x00 }); + + expected.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(expected); + + capture.assertHasFrame(OpCode.TEXT,1); + + Frame pActual = capture.getFrames().poll(); + Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0)); + } + + @Test + public void testParse_Text_FrameTooLargeDueToPolicy() throws Exception + { + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + // Artificially small buffer/payload + policy.setInputBufferSize(1024); // read buffer + policy.setMaxAllowedFrameSize(1024); // streaming buffer (not used in this test) + policy.setMaxTextMessageSize(1024); // actual maximum text message size policy + byte utf[] = new byte[2048]; + Arrays.fill(utf,(byte)'a'); + + Assert.assertThat("Must be a medium length payload",utf.length,allOf(greaterThan(0x7E),lessThan(0xFFFF))); + + ByteBuffer buf = ByteBuffer.allocate(utf.length + 8); + buf.put((byte)0x81); // text frame, fin = true + buf.put((byte)(0x80 | 0x7E)); // 0x7E == 126 (a 2 byte payload length) + buf.putShort((short)utf.length); + MaskedByteBuffer.putMask(buf); + MaskedByteBuffer.putPayload(buf,utf); + buf.flip(); + + ParserCapture capture = new ParserCapture(); + UnitParser parser = new UnitParser(policy,capture); + + expectedException.expect(MessageTooLargeException.class); + parser.parse(buf); + + capture.assertHasNoFrames(); + } + + @Test + public void testParse_Text_LongMasked() throws Exception + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 3500; i++) + { + sb.append("Hell\uFF4f Big W\uFF4Frld "); + } + sb.append(". The end."); + + String expectedText = sb.toString(); + byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); + + Assert.assertThat("Must be a long length payload",utf.length,greaterThan(0xFFFF)); + + ByteBuffer buf = ByteBuffer.allocate(utf.length + 32); + buf.put((byte)0x81); // text frame, fin = true + buf.put((byte)(0x80 | 0x7F)); // 0x7F == 127 (a 8 byte payload length) + buf.putLong(utf.length); + MaskedByteBuffer.putMask(buf); + MaskedByteBuffer.putPayload(buf,utf); + buf.flip(); + + WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); + policy.setMaxTextMessageSize(100000); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + WebSocketFrame txt = capture.getFrames().poll(); + Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); + } + + @Test + public void testParse_Text_ManySmallBuffers() { // Create frames byte payload[] = new byte[65536]; @@ -248,4 +1544,122 @@ public class ParserTest assertThat("Frame[0].payload[i]",actualPayload.get(i),is((byte)'*')); } } + + @Test + public void testParse_Text_MediumMasked() throws Exception + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 14; i++) + { + sb.append("Hell\uFF4f Medium W\uFF4Frld "); + } + sb.append(". The end."); + + String expectedText = sb.toString(); + byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); + + Assert.assertThat("Must be a medium length payload",utf.length,allOf(greaterThan(0x7E),lessThan(0xFFFF))); + + ByteBuffer buf = ByteBuffer.allocate(utf.length + 10); + buf.put((byte)0x81); + buf.put((byte)(0x80 | 0x7E)); // 0x7E == 126 (a 2 byte payload length) + buf.putShort((short)utf.length); + MaskedByteBuffer.putMask(buf); + MaskedByteBuffer.putPayload(buf,utf); + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + WebSocketFrame txt = capture.getFrames().poll(); + Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); + } + + @Test + public void testParse_Text_ShortMasked() throws Exception + { + String expectedText = "Hello World"; + byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); + + ByteBuffer buf = ByteBuffer.allocate(24); + buf.put((byte)0x81); + buf.put((byte)(0x80 | utf.length)); + MaskedByteBuffer.putMask(buf); + MaskedByteBuffer.putPayload(buf,utf); + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + WebSocketFrame txt = capture.getFrames().poll(); + Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); + } + + @Test + public void testParse_Text_ShortMaskedFragmented() throws Exception + { + String part1 = "Hello "; + String part2 = "World"; + + byte b1[] = part1.getBytes(StandardCharsets.UTF_8); + byte b2[] = part2.getBytes(StandardCharsets.UTF_8); + + ByteBuffer buf = ByteBuffer.allocate(32); + + // part 1 + buf.put((byte)0x01); // no fin + text + buf.put((byte)(0x80 | b1.length)); + MaskedByteBuffer.putMask(buf); + MaskedByteBuffer.putPayload(buf,b1); + + // part 2 + buf.put((byte)0x80); // fin + continuation + buf.put((byte)(0x80 | b2.length)); + MaskedByteBuffer.putMask(buf); + MaskedByteBuffer.putPayload(buf,b2); + + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + capture.assertHasFrame(OpCode.CONTINUATION,1); + WebSocketFrame txt = capture.getFrames().poll(); + Assert.assertThat("TextFrame[0].data",txt.getPayloadAsUTF8(),is(part1)); + txt = capture.getFrames().poll(); + Assert.assertThat("TextFrame[1].data",txt.getPayloadAsUTF8(),is(part2)); + } + + @Test + public void testParse_Text_ShortMaskedUtf8() throws Exception + { + String expectedText = "Hell\uFF4f W\uFF4Frld"; + + byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); + + ByteBuffer buf = ByteBuffer.allocate(24); + buf.put((byte)0x81); + buf.put((byte)(0x80 | utf.length)); + MaskedByteBuffer.putMask(buf); + MaskedByteBuffer.putPayload(buf,utf); + buf.flip(); + + WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + ParserCapture capture = new ParserCapture(); + Parser parser = new UnitParser(policy,capture); + parser.parse(buf); + + capture.assertHasFrame(OpCode.TEXT,1); + WebSocketFrame txt = capture.getFrames().poll(); + Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); + } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/PingPayloadParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/PingPayloadParserTest.java deleted file mode 100644 index c289eaa2f54..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/PingPayloadParserTest.java +++ /dev/null @@ -1,56 +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; - -import static org.hamcrest.Matchers.is; - -import java.nio.ByteBuffer; - -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.frames.PingFrame; -import org.eclipse.jetty.websocket.common.test.ParserCapture; -import org.eclipse.jetty.websocket.common.test.UnitParser; -import org.junit.Assert; -import org.junit.Test; - -public class PingPayloadParserTest -{ - @Test - public void testBasicPingParsing() - { - ByteBuffer buf = ByteBuffer.allocate(16); - BufferUtil.clearToFill(buf); - buf.put(new byte[] - { (byte)0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); - BufferUtil.flipToFlush(buf,0); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.PING,1); - PingFrame ping = (PingFrame)capture.getFrames().poll(); - - String actual = BufferUtil.toUTF8String(ping.getPayload()); - Assert.assertThat("PingFrame.payload",actual,is("Hello")); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesGeneratorTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesGeneratorTest.java deleted file mode 100644 index d6dc7eb6fe2..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesGeneratorTest.java +++ /dev/null @@ -1,191 +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; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -import org.eclipse.jetty.websocket.common.frames.BinaryFrame; -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.common.test.ByteBufferAssert; -import org.eclipse.jetty.websocket.common.test.UnitGenerator; -import org.junit.Test; - -public class RFC6455ExamplesGeneratorTest -{ - private static final int FUDGE = 32; - - @Test - public void testFragmentedUnmaskedTextMessage() - { - WebSocketFrame text1 = new TextFrame().setPayload("Hel").setFin(false); - WebSocketFrame text2 = new ContinuationFrame().setPayload("lo"); - - ByteBuffer actual1 = UnitGenerator.generate(text1); - ByteBuffer actual2 = UnitGenerator.generate(text2); - - ByteBuffer expected1 = ByteBuffer.allocate(5); - - expected1.put(new byte[] - { (byte)0x01, (byte)0x03, (byte)0x48, (byte)0x65, (byte)0x6c }); - - ByteBuffer expected2 = ByteBuffer.allocate(4); - - expected2.put(new byte[] - { (byte)0x80, (byte)0x02, (byte)0x6c, (byte)0x6f }); - - expected1.flip(); - expected2.flip(); - - ByteBufferAssert.assertEquals("t1 buffers are not equal",expected1,actual1); - ByteBufferAssert.assertEquals("t2 buffers are not equal",expected2,actual2); - } - - @Test - public void testSingleMaskedPongRequest() - { - PongFrame pong = new PongFrame().setPayload("Hello"); - pong.setMask(new byte[] - { 0x37, (byte)0xfa, 0x21, 0x3d }); - - ByteBuffer actual = UnitGenerator.generate(pong); - - ByteBuffer expected = ByteBuffer.allocate(11); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // Unmasked Pong request - expected.put(new byte[] - { (byte)0x8a, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); - expected.flip(); // make readable - - ByteBufferAssert.assertEquals("pong buffers are not equal",expected,actual); - } - - @Test - public void testSingleMaskedTextMessage() - { - WebSocketFrame text = new TextFrame().setPayload("Hello"); - text.setMask(new byte[] - { 0x37, (byte)0xfa, 0x21, 0x3d }); - - ByteBuffer actual = UnitGenerator.generate(text); - - ByteBuffer expected = ByteBuffer.allocate(11); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // A single-frame masked text message - expected.put(new byte[] - { (byte)0x81, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); - expected.flip(); // make readable - - ByteBufferAssert.assertEquals("masked text buffers are not equal",expected,actual); - } - - @Test - public void testSingleUnmasked256ByteBinaryMessage() - { - int dataSize = 256; - - BinaryFrame binary = new BinaryFrame(); - byte payload[] = new byte[dataSize]; - Arrays.fill(payload,(byte)0x44); - binary.setPayload(ByteBuffer.wrap(payload)); - - ByteBuffer actual = UnitGenerator.generate(binary); - - ByteBuffer expected = ByteBuffer.allocate(dataSize + FUDGE); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // 256 bytes binary message in a single unmasked frame - expected.put(new byte[] - { (byte)0x82, (byte)0x7E }); - expected.putShort((short)0x01_00); - - for (int i = 0; i < dataSize; i++) - { - expected.put((byte)0x44); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("binary buffers are not equal",expected,actual); - } - - @Test - public void testSingleUnmasked64KBinaryMessage() - { - int dataSize = 1024 * 64; - - BinaryFrame binary = new BinaryFrame(); - byte payload[] = new byte[dataSize]; - Arrays.fill(payload,(byte)0x44); - binary.setPayload(ByteBuffer.wrap(payload)); - - ByteBuffer actual = UnitGenerator.generate(binary); - - ByteBuffer expected = ByteBuffer.allocate(dataSize + 10); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // 64k bytes binary message in a single unmasked frame - expected.put(new byte[] - { (byte)0x82, (byte)0x7F }); - expected.putInt(0x00_00_00_00); - expected.putInt(0x00_01_00_00); - - for (int i = 0; i < dataSize; i++) - { - expected.put((byte)0x44); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("binary buffers are not equal",expected,actual); - } - - @Test - public void testSingleUnmaskedPingRequest() throws Exception - { - PingFrame ping = new PingFrame().setPayload("Hello"); - - ByteBuffer actual = UnitGenerator.generate(ping); - - ByteBuffer expected = ByteBuffer.allocate(10); - expected.put(new byte[] - { (byte)0x89, (byte)0x05, (byte)0x48, (byte)0x65, (byte)0x6c, (byte)0x6c, (byte)0x6f }); - expected.flip(); // make readable - - ByteBufferAssert.assertEquals("Ping buffers",expected,actual); - } - - @Test - public void testSingleUnmaskedTextMessage() - { - WebSocketFrame text = new TextFrame().setPayload("Hello"); - - ByteBuffer actual = UnitGenerator.generate(text); - - ByteBuffer expected = ByteBuffer.allocate(10); - - expected.put(new byte[] - { (byte)0x81, (byte)0x05, (byte)0x48, (byte)0x65, (byte)0x6c, (byte)0x6c, (byte)0x6f }); - - expected.flip(); - - ByteBufferAssert.assertEquals("t1 buffers are not equal",expected,actual); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java deleted file mode 100644 index 7d3dbc9c51f..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/RFC6455ExamplesParserTest.java +++ /dev/null @@ -1,238 +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; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -import java.nio.ByteBuffer; - -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.common.test.ParserCapture; -import org.eclipse.jetty.websocket.common.test.UnitParser; -import org.junit.Test; - -/** - * Collection of Example packets as found in RFC 6455 Examples section - */ -public class RFC6455ExamplesParserTest -{ - @Test - public void testFragmentedUnmaskedTextMessage() - { - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - - ByteBuffer buf = ByteBuffer.allocate(16); - BufferUtil.clearToFill(buf); - - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // A fragmented unmasked text message (part 1 of 2 "Hel") - buf.put(new byte[] - { (byte)0x01, (byte)0x03, 0x48, (byte)0x65, 0x6c }); - - // Parse #1 - BufferUtil.flipToFlush(buf,0); - parser.parse(buf); - - // part 2 of 2 "lo" (A continuation frame of the prior text message) - BufferUtil.flipToFill(buf); - buf.put(new byte[] - { (byte)0x80, 0x02, 0x6c, 0x6f }); - - // Parse #2 - BufferUtil.flipToFlush(buf,0); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - capture.assertHasFrame(OpCode.CONTINUATION,1); - - WebSocketFrame txt = capture.getFrames().poll(); - String actual = BufferUtil.toUTF8String(txt.getPayload()); - assertThat("TextFrame[0].data",actual,is("Hel")); - txt = capture.getFrames().poll(); - actual = BufferUtil.toUTF8String(txt.getPayload()); - assertThat("TextFrame[1].data",actual,is("lo")); - } - - @Test - public void testSingleMaskedPongRequest() - { - ByteBuffer buf = ByteBuffer.allocate(16); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // Unmasked Pong request - buf.put(new byte[] - { (byte)0x8a, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.PONG,1); - - WebSocketFrame pong = capture.getFrames().poll(); - String actual = BufferUtil.toUTF8String(pong.getPayload()); - assertThat("PongFrame.payload",actual,is("Hello")); - } - - @Test - public void testSingleMaskedTextMessage() - { - ByteBuffer buf = ByteBuffer.allocate(16); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // A single-frame masked text message - buf.put(new byte[] - { (byte)0x81, (byte)0x85, 0x37, (byte)0xfa, 0x21, 0x3d, 0x7f, (byte)0x9f, 0x4d, 0x51, 0x58 }); - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - - WebSocketFrame txt = capture.getFrames().poll(); - String actual = BufferUtil.toUTF8String(txt.getPayload()); - assertThat("TextFrame.payload",actual,is("Hello")); - } - - @Test - public void testSingleUnmasked256ByteBinaryMessage() - { - int dataSize = 256; - - ByteBuffer buf = ByteBuffer.allocate(dataSize + 10); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // 256 bytes binary message in a single unmasked frame - buf.put(new byte[] - { (byte)0x82, 0x7E }); - buf.putShort((short)0x01_00); // 16 bit size - for (int i = 0; i < dataSize; i++) - { - buf.put((byte)0x44); - } - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame bin = capture.getFrames().poll(); - - assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize)); - - ByteBuffer data = bin.getPayload(); - assertThat("BinaryFrame.payload.length",data.remaining(),is(dataSize)); - - for (int i = 0; i < dataSize; i++) - { - assertThat("BinaryFrame.payload[" + i + "]",data.get(i),is((byte)0x44)); - } - } - - @Test - public void testSingleUnmasked64KByteBinaryMessage() - { - int dataSize = 1024 * 64; - - ByteBuffer buf = ByteBuffer.allocate((dataSize + 10)); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // 64 Kbytes binary message in a single unmasked frame - buf.put(new byte[] - { (byte)0x82, 0x7F }); - buf.putLong(dataSize); // 64bit size - for (int i = 0; i < dataSize; i++) - { - buf.put((byte)0x77); - } - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - assertThat(parser.parse(buf), is(true)); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame bin = capture.getFrames().poll(); - - assertThat("BinaryFrame.payloadLength",bin.getPayloadLength(),is(dataSize)); - ByteBuffer data = bin.getPayload(); - assertThat("BinaryFrame.payload.length",data.remaining(),is(dataSize)); - - for (int i = 0; i < dataSize; i++) - { - assertThat("BinaryFrame.payload[" + i + "]",data.get(i),is((byte)0x77)); - } - } - - @Test - public void testSingleUnmaskedPingRequest() - { - ByteBuffer buf = ByteBuffer.allocate(16); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // Unmasked Ping request - buf.put(new byte[] - { (byte)0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.PING,1); - - WebSocketFrame ping = capture.getFrames().poll(); - String actual = BufferUtil.toUTF8String(ping.getPayload()); - assertThat("PingFrame.payload",actual,is("Hello")); - } - - @Test - public void testSingleUnmaskedTextMessage() - { - ByteBuffer buf = ByteBuffer.allocate(16); - // Raw bytes as found in RFC 6455, Section 5.7 - Examples - // A single-frame unmasked text message - buf.put(new byte[] - { (byte)0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }); - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - - WebSocketFrame txt = capture.getFrames().poll(); - String actual = BufferUtil.toUTF8String(txt.getPayload()); - assertThat("TextFrame.payload",actual,is("Hello")); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/TextPayloadParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/TextPayloadParserTest.java deleted file mode 100644 index a34979107ac..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/TextPayloadParserTest.java +++ /dev/null @@ -1,227 +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; - -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import org.eclipse.jetty.websocket.api.MessageTooLargeException; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.test.ParserCapture; -import org.eclipse.jetty.websocket.common.test.UnitParser; -import org.eclipse.jetty.websocket.common.util.MaskedByteBuffer; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TextPayloadParserTest -{ - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void testFrameTooLargeDueToPolicy() throws Exception - { - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - // Artificially small buffer/payload - policy.setInputBufferSize(1024); // read buffer - policy.setMaxAllowedFrameSize(1024); // streaming buffer (not used in this test) - policy.setMaxTextMessageSize(1024); // actual maximum text message size policy - byte utf[] = new byte[2048]; - Arrays.fill(utf,(byte)'a'); - - Assert.assertThat("Must be a medium length payload",utf.length,allOf(greaterThan(0x7E),lessThan(0xFFFF))); - - ByteBuffer buf = ByteBuffer.allocate(utf.length + 8); - buf.put((byte)0x81); // text frame, fin = true - buf.put((byte)(0x80 | 0x7E)); // 0x7E == 126 (a 2 byte payload length) - buf.putShort((short)utf.length); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,utf); - buf.flip(); - - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - - expectedException.expect(MessageTooLargeException.class); - parser.parse(buf); - - capture.assertHasNoFrames(); - } - - @Test - public void testLongMaskedText() throws Exception - { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 3500; i++) - { - sb.append("Hell\uFF4f Big W\uFF4Frld "); - } - sb.append(". The end."); - - String expectedText = sb.toString(); - byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); - - Assert.assertThat("Must be a long length payload",utf.length,greaterThan(0xFFFF)); - - ByteBuffer buf = ByteBuffer.allocate(utf.length + 32); - buf.put((byte)0x81); // text frame, fin = true - buf.put((byte)(0x80 | 0x7F)); // 0x7F == 127 (a 8 byte payload length) - buf.putLong(utf.length); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,utf); - buf.flip(); - - WebSocketPolicy policy = WebSocketPolicy.newServerPolicy(); - policy.setMaxTextMessageSize(100000); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame txt = capture.getFrames().poll(); - Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); - } - - @Test - public void testMediumMaskedText() throws Exception - { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 14; i++) - { - sb.append("Hell\uFF4f Medium W\uFF4Frld "); - } - sb.append(". The end."); - - String expectedText = sb.toString(); - byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); - - Assert.assertThat("Must be a medium length payload",utf.length,allOf(greaterThan(0x7E),lessThan(0xFFFF))); - - ByteBuffer buf = ByteBuffer.allocate(utf.length + 10); - buf.put((byte)0x81); - buf.put((byte)(0x80 | 0x7E)); // 0x7E == 126 (a 2 byte payload length) - buf.putShort((short)utf.length); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,utf); - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame txt = capture.getFrames().poll(); - Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); - } - - @Test - public void testShortMaskedFragmentedText() throws Exception - { - String part1 = "Hello "; - String part2 = "World"; - - byte b1[] = part1.getBytes(StandardCharsets.UTF_8); - byte b2[] = part2.getBytes(StandardCharsets.UTF_8); - - ByteBuffer buf = ByteBuffer.allocate(32); - - // part 1 - buf.put((byte)0x01); // no fin + text - buf.put((byte)(0x80 | b1.length)); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,b1); - - // part 2 - buf.put((byte)0x80); // fin + continuation - buf.put((byte)(0x80 | b2.length)); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,b2); - - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - capture.assertHasFrame(OpCode.CONTINUATION,1); - WebSocketFrame txt = capture.getFrames().poll(); - Assert.assertThat("TextFrame[0].data",txt.getPayloadAsUTF8(),is(part1)); - txt = capture.getFrames().poll(); - Assert.assertThat("TextFrame[1].data",txt.getPayloadAsUTF8(),is(part2)); - } - - @Test - public void testShortMaskedText() throws Exception - { - String expectedText = "Hello World"; - byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); - - ByteBuffer buf = ByteBuffer.allocate(24); - buf.put((byte)0x81); - buf.put((byte)(0x80 | utf.length)); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,utf); - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame txt = capture.getFrames().poll(); - Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); - } - - @Test - public void testShortMaskedUtf8Text() throws Exception - { - String expectedText = "Hell\uFF4f W\uFF4Frld"; - - byte utf[] = expectedText.getBytes(StandardCharsets.UTF_8); - - ByteBuffer buf = ByteBuffer.allocate(24); - buf.put((byte)0x81); - buf.put((byte)(0x80 | utf.length)); - MaskedByteBuffer.putMask(buf); - MaskedByteBuffer.putPayload(buf,utf); - buf.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(buf); - - capture.assertHasFrame(OpCode.TEXT,1); - WebSocketFrame txt = capture.getFrames().poll(); - Assert.assertThat("TextFrame.data",txt.getPayloadAsUTF8(),is(expectedText)); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java deleted file mode 100644 index a234eef173b..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_1.java +++ /dev/null @@ -1,503 +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.ab; - -import static org.hamcrest.Matchers.is; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.common.Generator; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.frames.TextFrame; -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.junit.Assert; -import org.junit.Test; - -/** - * Text Message Spec testing the {@link Generator} and {@link Parser} - */ -public class TestABCase1_1 -{ - private WebSocketPolicy policy = WebSocketPolicy.newClientPolicy(); - - @Test - public void testGenerate125ByteTextCase1_1_2() - { - int length = 125; - byte buf[] = new byte[length]; - Arrays.fill(buf,(byte)'*'); - String text = new String(buf,StandardCharsets.UTF_8); - - Frame textFrame = new TextFrame().setPayload(text); - - ByteBuffer actual = UnitGenerator.generate(textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= length & 0x7F; - expected.put(b); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate126ByteTextCase1_1_3() - { - int length = 126; - - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < length; ++i) - { - builder.append("*"); - } - - WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); - - ByteBuffer actual = UnitGenerator.generate(textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - - // expected.put((byte)((length>>8) & 0xFF)); - // expected.put((byte)(length & 0xFF)); - expected.putShort((short)length); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate127ByteTextCase1_1_4() - { - int length = 127; - - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < length; ++i) - { - builder.append("*"); - } - - WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); - - ByteBuffer actual = UnitGenerator.generate(textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - - // expected.put((byte)((length>>8) & 0xFF)); - // expected.put((byte)(length & 0xFF)); - expected.putShort((short)length); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate128ByteTextCase1_1_5() - { - int length = 128; - - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < length; ++i) - { - builder.append("*"); - } - - WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); - - ByteBuffer actual = UnitGenerator.generate(textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - - expected.put((byte)(length >> 8)); - expected.put((byte)(length & 0xFF)); - // expected.putShort((short)length); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate65535ByteTextCase1_1_6() - { - int length = 65535; - - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < length; ++i) - { - builder.append("*"); - } - - WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); - - ByteBuffer actual = UnitGenerator.generate(textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.put(new byte[] - { (byte)0xff, (byte)0xff }); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate65536ByteTextCase1_1_7() - { - int length = 65536; - - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < length; ++i) - { - builder.append("*"); - } - - WebSocketFrame textFrame = new TextFrame().setPayload(builder.toString()); - - ByteBuffer actual = UnitGenerator.generate(textFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 11); - - expected.put(new byte[] - { (byte)0x81 }); - - byte b = 0x00; // no masking - b |= 0x7F; - expected.put(b); - expected.put(new byte[] - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerateEmptyTextCase1_1_1() - { - WebSocketFrame textFrame = new TextFrame().setPayload(""); - - ByteBuffer actual = UnitGenerator.generate(textFrame); - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x81, (byte)0x00 }); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testParse125ByteTextCase1_1_2() - { - int length = 125; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - byte b = 0x00; // no masking - b |= length & 0x7F; - expected.put(b); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.TEXT,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse126ByteTextCase1_1_3() - { - int length = 126; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - expected.putShort((short)length); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.TEXT,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse127ByteTextCase1_1_4() - { - int length = 127; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - expected.putShort((short)length); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.TEXT,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse128ByteTextCase1_1_5() - { - int length = 128; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.putShort((short)length); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.TEXT,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // .assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse65535ByteTextCase1_1_6() - { - int length = 65535; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x81 }); - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.put(new byte[] - { (byte)0xff, (byte)0xff }); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - policy.setMaxTextMessageSize(length); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.TEXT,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // Assert.assertEquals("TextFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse65536ByteTextCase1_1_7() - { - int length = 65536; - - ByteBuffer expected = ByteBuffer.allocate(length + 11); - - expected.put(new byte[] - { (byte)0x81 }); - byte b = 0x00; // no masking - b |= 0x7F; - expected.put(b); - expected.put(new byte[] - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }); - - for (int i = 0; i < length; ++i) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - policy.setMaxTextMessageSize(length); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.TEXT,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(length)); - } - - @Test - public void testParseEmptyTextCase1_1_1() - { - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x81, (byte)0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.TEXT,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("TextFrame.payloadLength",pActual.getPayloadLength(),is(0)); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java deleted file mode 100644 index 4fe7c7ac003..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase1_2.java +++ /dev/null @@ -1,518 +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.ab; - -import static org.hamcrest.Matchers.is; - -import java.nio.ByteBuffer; - -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.common.Generator; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.frames.BinaryFrame; -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.junit.Assert; -import org.junit.Test; - -/** - * Binary Message Spec testing the {@link Generator} and {@link Parser} - */ -public class TestABCase1_2 -{ - private WebSocketPolicy policy = WebSocketPolicy.newClientPolicy(); - - @Test - public void testGenerate125ByteBinaryCase1_2_2() - { - int length = 125; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - } - - bb.flip(); - - WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); - - ByteBuffer actual = UnitGenerator.generate(binaryFrame); - - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= length & 0x7F; - expected.put(b); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - BufferUtil.flipToFlush(expected,0); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate126ByteBinaryCase1_2_3() - { - int length = 126; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - } - - bb.flip(); - - WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); - - ByteBuffer actual = UnitGenerator.generate(binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - - //expected.put((byte)((length>>8) & 0xFF)); - //expected.put((byte)(length & 0xFF)); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - BufferUtil.flipToFlush(expected,0); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate127ByteBinaryCase1_2_4() - { - int length = 127; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - - WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); - - ByteBuffer actual = UnitGenerator.generate(binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - - //expected.put((byte)((length>>8) & 0xFF)); - //expected.put((byte)(length & 0xFF)); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - BufferUtil.flipToFlush(expected,0); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate128ByteBinaryCase1_2_5() - { - int length = 128; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); - - ByteBuffer actual = UnitGenerator.generate(binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - - expected.put((byte)(length>>8)); - expected.put((byte)(length & 0xFF)); - //expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - BufferUtil.flipToFlush(expected,0); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - - } - - @Test - public void testGenerate65535ByteBinaryCase1_2_6() - { - int length = 65535; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - - WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); - - ByteBuffer actual = UnitGenerator.generate(binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.put(new byte[]{ (byte)0xff, (byte)0xff}); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - BufferUtil.flipToFlush(expected,0); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerate65536ByteBinaryCase1_2_7() - { - int length = 65536; - - ByteBuffer bb = ByteBuffer.allocate(length); - - for ( int i = 0 ; i < length ; ++i) - { - bb.put("*".getBytes()); - - } - - bb.flip(); - - WebSocketFrame binaryFrame = new BinaryFrame().setPayload(bb); - - ByteBuffer actual = UnitGenerator.generate(binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(length + 11); - - expected.put(new byte[] - { (byte)0x82 }); - - byte b = 0x00; // no masking - b |= 0x7F; - expected.put(b); - expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); - - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - BufferUtil.flipToFlush(expected,0); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerateEmptyBinaryCase1_2_1() - { - WebSocketFrame binaryFrame = new BinaryFrame().setPayload(new byte[] {}); - - ByteBuffer actual = UnitGenerator.generate(binaryFrame); - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x82, (byte)0x00 }); - - BufferUtil.flipToFlush(expected,0); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testParse125ByteBinaryCase1_2_2() - { - int length = 125; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - byte b = 0x00; // no masking - b |= length & 0x7F; - expected.put(b); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse126ByteBinaryCase1_2_3() - { - int length = 126; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // Assert.assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse127ByteBinaryCase1_2_4() - { - int length = 127; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - byte b = 0x00; // no masking - b |= length & 0x7E; - expected.put(b); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - // .assertEquals("BinaryFrame.payload",length,pActual.getPayloadData().length); - } - - @Test - public void testParse128ByteBinaryCase1_2_5() - { - int length = 128; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.putShort((short)length); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - } - - @Test - public void testParse65535ByteBinaryCase1_2_6() - { - int length = 65535; - - ByteBuffer expected = ByteBuffer.allocate(length + 5); - - expected.put(new byte[] - { (byte)0x82 }); - byte b = 0x00; // no masking - b |= 0x7E; - expected.put(b); - expected.put(new byte[]{ (byte)0xff, (byte)0xff}); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - expected.flip(); - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - policy.setMaxBinaryMessageSize(length); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - } - - @Test - public void testParse65536ByteBinaryCase1_2_7() - { - int length = 65536; - - ByteBuffer expected = ByteBuffer.allocate(length + 11); - - expected.put(new byte[] - { (byte)0x82 }); - byte b = 0x00; // no masking - b |= 0x7F; - expected.put(b); - expected.put(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}); - - for ( int i = 0 ; i < length ; ++i ) - { - expected.put("*".getBytes()); - } - - expected.flip(); - - WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - policy.setMaxBinaryMessageSize(length); - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(length)); - } - - @Test - public void testParseEmptyBinaryCase1_2_1() - { - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x82, (byte)0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.BINARY,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("BinaryFrame.payloadLength",pActual.getPayloadLength(),is(0)); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java deleted file mode 100644 index 85e9595e893..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase2.java +++ /dev/null @@ -1,319 +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.ab; - -import static org.hamcrest.Matchers.is; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.websocket.api.ProtocolException; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketException; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.common.Generator; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.frames.PingFrame; -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.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TestABCase2 -{ - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - - @Test - public void testGenerate125OctetPingCase2_4() - { - byte[] bytes = new byte[125]; - - for ( int i = 0 ; i < bytes.length ; ++i ) - { - bytes[i] = Integer.valueOf(Integer.toOctalString(i)).byteValue(); - } - - WebSocketFrame pingFrame = new PingFrame().setPayload(bytes); - - ByteBuffer actual = UnitGenerator.generate(pingFrame); - - ByteBuffer expected = ByteBuffer.allocate(bytes.length + 32); - - expected.put(new byte[] - { (byte)0x89 }); - - byte b = 0x00; // no masking - b |= bytes.length & 0x7F; - expected.put(b); - expected.put(bytes); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerateBinaryPingCase2_3() - { - byte[] bytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; - - PingFrame pingFrame = new PingFrame().setPayload(bytes); - - ByteBuffer actual = UnitGenerator.generate(pingFrame); - - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] - { (byte)0x89 }); - - byte b = 0x00; // no masking - b |= bytes.length & 0x7F; - expected.put(b); - expected.put(bytes); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - - @Test - public void testGenerateEmptyPingCase2_1() - { - WebSocketFrame pingFrame = new PingFrame(); - - ByteBuffer actual = UnitGenerator.generate(pingFrame); - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x89, (byte)0x00 }); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testGenerateHelloPingCase2_2() - { - String message = "Hello, world!"; - byte[] messageBytes = StringUtil.getUtf8Bytes(message); - - PingFrame pingFrame = new PingFrame().setPayload(messageBytes); - - ByteBuffer actual = UnitGenerator.generate(pingFrame); - - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] - { (byte)0x89 }); - - byte b = 0x00; // no masking - b |= messageBytes.length & 0x7F; - expected.put(b); - expected.put(messageBytes); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test( expected=WebSocketException.class ) - public void testGenerateOversizedBinaryPingCase2_5_A() - { - byte[] bytes = new byte[126]; - Arrays.fill(bytes,(byte)0x00); - - PingFrame pingFrame = new PingFrame(); - pingFrame.setPayload(ByteBuffer.wrap(bytes)); // should throw exception - } - - @Test( expected=WebSocketException.class ) - public void testGenerateOversizedBinaryPingCase2_5_B() - { - byte[] bytes = new byte[126]; - Arrays.fill(bytes, (byte)0x00); - - PingFrame pingFrame = new PingFrame(); - pingFrame.setPayload(ByteBuffer.wrap(bytes)); // should throw exception - - // FIXME: Remove? UnitGenerator.generate(pingFrame); - } - - @Test - public void testParse125OctetPingCase2_4() - { - byte[] bytes = new byte[125]; - - for ( int i = 0 ; i < bytes.length ; ++i ) - { - bytes[i] = Integer.valueOf(Integer.toOctalString(i)).byteValue(); - } - - ByteBuffer expected = ByteBuffer.allocate(bytes.length + 32); - - expected.put(new byte[] - { (byte)0x89 }); - - byte b = 0x00; // no masking - b |= bytes.length & 0x7F; - expected.put(b); - expected.put(bytes); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.PING,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length)); - Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); - } - - @Test - public void testParseBinaryPingCase2_3() - { - byte[] bytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; - - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] - { (byte)0x89 }); - - byte b = 0x00; // no masking - b |= bytes.length & 0x7F; - expected.put(b); - expected.put(bytes); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.PING,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(bytes.length)); - Assert.assertEquals("PingFrame.payload",bytes.length,pActual.getPayloadLength()); - } - - @Test - public void testParseEmptyPingCase2_1() - { - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x89, (byte)0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.PING,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(0)); - Assert.assertEquals("PingFrame.payload",0,pActual.getPayloadLength()); - } - - @Test - public void testParseHelloPingCase2_2() - { - String message = "Hello, world!"; - byte[] messageBytes = message.getBytes(); - - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] - { (byte)0x89 }); - - byte b = 0x00; // no masking - b |= messageBytes.length & 0x7F; - expected.put(b); - expected.put(messageBytes); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.PING,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("PingFrame.payloadLength",pActual.getPayloadLength(),is(message.length())); - Assert.assertEquals("PingFrame.payload",message.length(),pActual.getPayloadLength()); - } - - @Test - public void testParseOversizedBinaryPingCase2_5() - { - byte[] bytes = new byte[126]; - Arrays.fill(bytes,(byte)0x00); - - ByteBuffer expected = ByteBuffer.allocate(bytes.length + Generator.MAX_HEADER_LENGTH); - - byte b; - - // fin + op - b = 0x00; - b |= 0x80; // fin on - b |= 0x09; // ping - expected.put(b); - - // mask + len - b = 0x00; - b |= 0x00; // no masking - b |= 0x7E; // 2 byte len - expected.put(b); - - // 2 byte len - expected.putChar((char)bytes.length); - - // payload - expected.put(bytes); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - - expectedException.expect(ProtocolException.class); - parser.parse(expected); - } - -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java deleted file mode 100644 index 04e7914c251..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase4.java +++ /dev/null @@ -1,109 +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.ab; - -import static org.hamcrest.CoreMatchers.containsString; - -import java.nio.ByteBuffer; - -import org.eclipse.jetty.websocket.api.ProtocolException; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.test.ParserCapture; -import org.eclipse.jetty.websocket.common.test.UnitParser; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TestABCase4 -{ - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - - @Test - public void testParserControlOpCode11Case4_2_1() throws Exception - { - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] { (byte)0x8b, 0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - - expectedException.expect(ProtocolException.class); - expectedException.expectMessage(containsString("Unknown opcode: 11")); - parser.parse(expected); - } - - @Test - public void testParserControlOpCode12WithPayloadCase4_2_2() throws Exception - { - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] { (byte)0x8c, 0x01, 0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy, capture); - - expectedException.expect(ProtocolException.class); - expectedException.expectMessage(containsString("Unknown opcode: 12")); - parser.parse(expected); - } - - @Test - public void testParserNonControlOpCode3Case4_1_1() throws Exception - { - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] { (byte)0x83, 0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy, capture); - - expectedException.expect(ProtocolException.class); - expectedException.expectMessage(containsString("Unknown opcode: 3")); - parser.parse(expected); - } - - @Test - public void testParserNonControlOpCode4WithPayloadCase4_1_2() throws Exception - { - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] { (byte)0x84, 0x01, 0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - - expectedException.expect(ProtocolException.class); - expectedException.expectMessage(containsString("Unknown opcode: 4")); - parser.parse(expected); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java deleted file mode 100644 index 61d3be87153..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase7_3.java +++ /dev/null @@ -1,332 +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.ab; - -import static org.hamcrest.Matchers.is; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.api.ProtocolException; -import org.eclipse.jetty.websocket.api.WebSocketBehavior; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.frames.CloseFrame; -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.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TestABCase7_3 -{ - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); - - @Test - public void testCase7_3_1GenerateEmptyClose() - { - CloseInfo close = new CloseInfo(); - - ByteBuffer actual = UnitGenerator.generate(close.asFrame()); - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x88, (byte)0x00 }); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testCase7_3_1ParseEmptyClose() - { - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x88, (byte)0x00 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.CLOSE,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(0)); - } - - @Test(expected = ProtocolException.class) - public void testCase7_3_2Generate1BytePayloadClose() - { - CloseFrame closeFrame = new CloseFrame(); - closeFrame.setPayload(Hex.asByteBuffer("00")); - - UnitGenerator.generate(closeFrame); - } - - @Test - public void testCase7_3_2Parse1BytePayloadClose() - { - ByteBuffer expected = Hex.asByteBuffer("880100"); - - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - - expectedException.expect(ProtocolException.class); - expectedException.expectMessage(CoreMatchers.containsString("Invalid close frame payload length")); - parser.parse(expected); - } - - @Test - public void testCase7_3_3GenerateCloseWithStatus() - { - CloseInfo close = new CloseInfo(1000); - - ByteBuffer actual = UnitGenerator.generate(close.asFrame()); - - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 }); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testCase7_3_3ParseCloseWithStatus() - { - ByteBuffer expected = ByteBuffer.allocate(5); - - expected.put(new byte[] - { (byte)0x88, (byte)0x02, 0x03, (byte)0xe8 }); - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.CLOSE,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(2)); - } - - @Test - public void testCase7_3_4GenerateCloseWithStatusReason() - { - String message = "bad cough"; - byte[] messageBytes = message.getBytes(); - - CloseInfo close = new CloseInfo(1000,message); - - ByteBuffer actual = UnitGenerator.generate(close.asFrame()); - - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] - { (byte)0x88 }); - - byte b = 0x00; // no masking - b |= (message.length() + 2) & 0x7F; - expected.put(b); - expected.putShort((short)1000); - expected.put(messageBytes); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testCase7_3_4ParseCloseWithStatusReason() - { - String message = "bad cough"; - byte[] messageBytes = message.getBytes(); - - ByteBuffer expected = ByteBuffer.allocate(32); - - expected.put(new byte[] - { (byte)0x88 }); - byte b = 0x00; // no masking - b |= (messageBytes.length + 2) & 0x7F; - expected.put(b); - expected.putShort((short)1000); - expected.put(messageBytes); - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.CLOSE,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(messageBytes.length + 2)); - } - - - @Test - public void testCase7_3_5GenerateCloseWithStatusMaxReason() - { - StringBuilder message = new StringBuilder(); - for ( int i = 0 ; i < 123 ; ++i ) - { - message.append("*"); - } - - CloseInfo close = new CloseInfo(1000,message.toString()); - - ByteBuffer actual = UnitGenerator.generate(close.asFrame()); - ByteBuffer expected = ByteBuffer.allocate(132); - - byte messageBytes[] = message.toString().getBytes(StandardCharsets.UTF_8); - - expected.put(new byte[] - { (byte)0x88 }); - - byte b = 0x00; // no masking - b |= (messageBytes.length + 2) & 0x7F; - expected.put(b); - expected.putShort((short)1000); - - expected.put(messageBytes); - - expected.flip(); - - ByteBufferAssert.assertEquals("buffers do not match",expected,actual); - } - - @Test - public void testCase7_3_5ParseCloseWithStatusMaxReason() - { - StringBuilder message = new StringBuilder(); - for ( int i = 0 ; i < 123 ; ++i ) - { - message.append("*"); - } - - byte[] messageBytes = message.toString().getBytes(StandardCharsets.UTF_8); - - ByteBuffer expected = ByteBuffer.allocate(132); - - expected.put(new byte[] - { (byte)0x88 }); - byte b = 0x00; // no masking - - b |= (messageBytes.length + 2) & 0x7F; - expected.put(b); - expected.putShort((short)1000); - - expected.put(messageBytes); - expected.flip(); - - ParserCapture capture = new ParserCapture(); - Parser parser = new UnitParser(policy,capture); - parser.parse(expected); - - capture.assertHasFrame(OpCode.CLOSE,1); - - Frame pActual = capture.getFrames().poll(); - Assert.assertThat("CloseFrame.payloadLength",pActual.getPayloadLength(),is(125)); - } - - @Test(expected = ProtocolException.class) - public void testCase7_3_6GenerateCloseWithInvalidStatusReason() - { - StringBuilder message = new StringBuilder(); - for ( int i = 0 ; i < 124 ; ++i ) - { - message.append("*"); - } - - byte[] messageBytes = message.toString().getBytes(); - - CloseFrame closeFrame = new CloseFrame(); - - ByteBuffer bb = ByteBuffer.allocate(CloseFrame.MAX_CONTROL_PAYLOAD + 1); // 126 which is too big for control - - bb.putChar((char)1000); - bb.put(messageBytes); - - BufferUtil.flipToFlush(bb,0); - - closeFrame.setPayload(bb); - - UnitGenerator.generate(closeFrame); - } - - @Test - public void testCase7_3_6ParseCloseWithInvalidStatusReason() - { - byte[] messageBytes = new byte[124]; - Arrays.fill(messageBytes,(byte)'*'); - - ByteBuffer expected = ByteBuffer.allocate(256); - - byte b; - - // fin + op - b = 0x00; - b |= 0x80; // fin on - b |= 0x08; // close - expected.put(b); - - // mask + len - b = 0x00; - b |= 0x00; // no masking - b |= 0x7E; // 2 byte len - expected.put(b); - - // 2 byte len - expected.putChar((char)(messageBytes.length + 2)); - - // payload - expected.putShort((short)1000); // status code - expected.put(messageBytes); // reason - - expected.flip(); - - ParserCapture capture = new ParserCapture(); - UnitParser parser = new UnitParser(policy,capture); - - expectedException.expect(ProtocolException.class); - expectedException.expectMessage(CoreMatchers.containsString("Invalid control frame payload length")); - parser.parse(expected); - } -}