Initial pass at testing

This commit is contained in:
Joakim Erdfelt 2012-06-18 15:41:38 -07:00
parent f3532f9bd9
commit 7227a86254
15 changed files with 331 additions and 29 deletions

View File

@ -54,18 +54,7 @@ public class BaseFrame
*/
public BaseFrame(BaseFrame copy) {
this();
this.fin = copy.fin;
this.rsv1 = copy.rsv1;
this.rsv2 = copy.rsv2;
this.rsv3 = copy.rsv3;
this.opcode = copy.opcode;
this.masked = copy.masked;
this.payloadLength = copy.payloadLength;
if(copy.mask != null) {
int mlen = copy.mask.length;
this.mask = new byte[mlen];
System.arraycopy(copy.mask,0,this.mask,0,mlen);
}
copy(copy);
}
/**
@ -76,6 +65,27 @@ public class BaseFrame
this.opcode = opcode;
}
/**
* Copy the baseframe values
*
* @param copy
*/
public void copy(BaseFrame copy) {
this.fin = copy.fin;
this.rsv1 = copy.rsv1;
this.rsv2 = copy.rsv2;
this.rsv3 = copy.rsv3;
this.opcode = copy.opcode;
this.masked = copy.masked;
this.payloadLength = copy.payloadLength;
if (copy.mask != null)
{
int mlen = copy.mask.length;
this.mask = new byte[mlen];
System.arraycopy(copy.mask,0,this.mask,0,mlen);
}
}
public byte[] getMask()
{
if (!masked)

View File

@ -1,20 +1,33 @@
package org.eclipse.jetty.websocket.frames;
import org.eclipse.jetty.websocket.api.OpCode;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.OpCode;
import org.eclipse.jetty.websocket.api.WebSocketException;
/**
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">Ping Frame (0x09)</a>.
*/
public class PingFrame extends ControlFrame
{
{
private ByteBuffer payload;
public PingFrame(ByteBuffer payload)
/**
* Default constructor
*/
public PingFrame()
{
super(OpCode.PING);
}
/**
* Construct Ping Frame from known bytebuffer
*
* @param payload
*/
public PingFrame(ByteBuffer payload)
{
this();
setPayload(payload);
}
@ -24,6 +37,11 @@ public class PingFrame extends ControlFrame
return OpCode.PING;
}
public ByteBuffer getPayload()
{
return payload;
}
public void setPayload(ByteBuffer payload)
{
if ( payload.array().length >= 126 )
@ -36,12 +54,7 @@ public class PingFrame extends ControlFrame
throw new WebSocketException("too long, catch this better");
}
}
public ByteBuffer getPayload()
{
return payload;
}
@Override
public String toString()
{

View File

@ -4,6 +4,12 @@ import java.nio.ByteBuffer;
public class BinaryPayloadParser extends PayloadParser
{
private Parser baseParser;
public BinaryPayloadParser(Parser parser)
{
this.baseParser = parser;
}
@Override
public boolean parse(ByteBuffer buffer)
@ -12,4 +18,11 @@ public class BinaryPayloadParser extends PayloadParser
return false;
}
@Override
public void reset()
{
// TODO Auto-generated method stub
}
}

View File

@ -4,6 +4,12 @@ import java.nio.ByteBuffer;
public class ClosePayloadParser extends PayloadParser
{
private Parser baseParser;
public ClosePayloadParser(Parser parser)
{
this.baseParser = parser;
}
@Override
public boolean parse(ByteBuffer buffer)
@ -12,4 +18,11 @@ public class ClosePayloadParser extends PayloadParser
return false;
}
@Override
public void reset()
{
// TODO Auto-generated method stub
}
}

View File

@ -4,6 +4,12 @@ import java.nio.ByteBuffer;
public class ContinuationPayloadParser extends PayloadParser
{
private Parser baseParser;
public ContinuationPayloadParser(Parser parser)
{
this.baseParser = parser;
}
@Override
public boolean parse(ByteBuffer buffer)
@ -12,4 +18,10 @@ public class ContinuationPayloadParser extends PayloadParser
return false;
}
@Override
public void reset()
{
// TODO Auto-generated method stub
}
}

View File

@ -94,12 +94,12 @@ public class Parser {
baseframe = new BaseFrame();
reset();
parsers.put(OpCode.CONTINUATION,new ContinuationPayloadParser());
parsers.put(OpCode.TEXT,new TextPayloadParser());
parsers.put(OpCode.BINARY,new BinaryPayloadParser());
parsers.put(OpCode.CLOSE,new ClosePayloadParser());
parsers.put(OpCode.PING,new PingPayloadParser());
parsers.put(OpCode.PONG,new PongPayloadParser());
parsers.put(OpCode.CONTINUATION,new ContinuationPayloadParser(this));
parsers.put(OpCode.TEXT,new TextPayloadParser(this));
parsers.put(OpCode.BINARY,new BinaryPayloadParser(this));
parsers.put(OpCode.CLOSE,new ClosePayloadParser(this));
parsers.put(OpCode.PING,new PingPayloadParser(this));
parsers.put(OpCode.PONG,new PongPayloadParser(this));
}
public void addListener(Listener listener)
@ -107,6 +107,11 @@ public class Parser {
listeners.add(listener);
}
protected BaseFrame getBaseFrame()
{
return baseframe;
}
protected void notifyControlFrame(final ControlFrame f)
{
LOG.debug("Notify Control Frame: {}",f);

View File

@ -5,4 +5,5 @@ import java.nio.ByteBuffer;
public abstract class PayloadParser
{
public abstract boolean parse(ByteBuffer buffer);
public abstract void reset();
}

View File

@ -2,14 +2,60 @@ package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.frames.PingFrame;
/**
* Parsing for the {@link PingFrame}.
*/
public class PingPayloadParser extends PayloadParser
{
private Parser baseParser;
private ByteBuffer payload;
private int payloadLength;
public PingPayloadParser(Parser parser)
{
this.baseParser = parser;
}
private void onPingFrame()
{
PingFrame ping = new PingFrame();
ping.copy(baseParser.getBaseFrame());
ping.setPayload(payload);
baseParser.notifyControlFrame(ping);
}
@Override
public boolean parse(ByteBuffer buffer)
{
// TODO Auto-generated method stub
payloadLength = baseParser.getBaseFrame().getPayloadLength();
while (buffer.hasRemaining())
{
if (payload == null)
{
// TODO: buffer size limits
payload = ByteBuffer.allocate(payloadLength);
}
int size = Math.min(payloadLength,buffer.remaining());
int limit = buffer.limit();
buffer.limit(buffer.position() + size);
ByteBuffer bytes = buffer.slice();
buffer.limit(limit);
payload.put(bytes);
if (payload.position() >= payloadLength)
{
onPingFrame();
return true;
}
}
return false;
}
@Override
public void reset()
{
payload = null;
}
}

View File

@ -4,6 +4,12 @@ import java.nio.ByteBuffer;
public class PongPayloadParser extends PayloadParser
{
private Parser baseParser;
public PongPayloadParser(Parser parser)
{
this.baseParser = parser;
}
@Override
public boolean parse(ByteBuffer buffer)
@ -12,4 +18,11 @@ public class PongPayloadParser extends PayloadParser
return false;
}
@Override
public void reset()
{
// TODO Auto-generated method stub
}
}

View File

@ -4,6 +4,12 @@ import java.nio.ByteBuffer;
public class TextPayloadParser extends PayloadParser
{
private Parser baseParser;
public TextPayloadParser(Parser parser)
{
this.baseParser = parser;
}
@Override
public boolean parse(ByteBuffer buffer)
@ -12,4 +18,11 @@ public class TextPayloadParser extends PayloadParser
return false;
}
@Override
public void reset()
{
// TODO Auto-generated method stub
}
}

View File

@ -12,4 +12,11 @@ public class UnknownPayloadParser extends PayloadParser
return false;
}
@Override
public void reset()
{
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,24 @@
package org.eclipse.jetty.websocket;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StdErrLog;
/**
* Utility class for managing logging levels during unit testing
*/
public class TestLogging
{
public static void enableDebug(Class<?> clazz)
{
setLevel(clazz,StdErrLog.LEVEL_DEBUG);
}
public static void setLevel(Class<?> clazz, int level)
{
Logger log = Log.getLogger(clazz);
if(log instanceof StdErrLog) {
((StdErrLog)log).setLevel(level);
}
}
}

View File

@ -0,0 +1,74 @@
package org.eclipse.jetty.websocket.parser;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.frames.ControlFrame;
import org.eclipse.jetty.websocket.frames.DataFrame;
import org.junit.Assert;
public class FrameParseCapture implements Parser.Listener
{
private List<BaseFrame> frames = new ArrayList<>();
private List<WebSocketException> errors = new ArrayList<>();
public void assertHasFrame(Class<? extends BaseFrame> frameType)
{
Assert.assertThat(frameType.getSimpleName(),getFrameCount(frameType),greaterThanOrEqualTo(1));
}
public void assertHasFrame(Class<? extends BaseFrame> frameType, int expectedCount)
{
Assert.assertThat(frameType.getSimpleName(),getFrameCount(frameType),is(expectedCount));
}
public void assertNoErrors()
{
Assert.assertThat("Has no errors",errors.size(),is(0));
}
public List<WebSocketException> getErrors()
{
return errors;
}
public int getFrameCount(Class<? extends BaseFrame> frameType)
{
int count = 0;
for(BaseFrame frame: frames) {
if (frame.getClass().isInstance(frameType))
{
count++;
}
}
return count;
}
public List<BaseFrame> getFrames()
{
return frames;
}
@Override
public void onControlFrame(ControlFrame frame)
{
frames.add(frame);
}
@Override
public void onDataFrame(DataFrame frame)
{
frames.add(frame);
}
@Override
public void onWebSocketException(WebSocketException e)
{
errors.add(e);
}
}

View File

@ -0,0 +1,27 @@
package org.eclipse.jetty.websocket.parser;
import static org.hamcrest.Matchers.is;
import java.nio.ByteBuffer;
import org.junit.Assert;
import org.junit.Test;
public class ParserTest
{
@Test
public void testParseNothing()
{
ByteBuffer buf = ByteBuffer.allocate(16);
// Put nothing in the buffer.
buf.flip();
Parser parser = new Parser();
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(buf);
capture.assertNoErrors();
Assert.assertThat("Frame Count",capture.getFrames().size(),is(0));
}
}

View File

@ -0,0 +1,31 @@
package org.eclipse.jetty.websocket.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.TestLogging;
import org.eclipse.jetty.websocket.frames.PingFrame;
import org.junit.Test;
public class PingParserTest
{
@Test
public void testBasicPingParsing()
{
TestLogging.enableDebug(Parser.class);
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();
Parser parser = new Parser();
FrameParseCapture capture = new FrameParseCapture();
parser.addListener(capture);
parser.parse(buf);
capture.assertNoErrors();
capture.assertHasFrame(PingFrame.class,1);
}
}