#9900: simplify and add test
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
parent
52e182486d
commit
382638b84d
|
@ -66,7 +66,7 @@ public class Parser
|
|||
{
|
||||
this.bufferPool = bufferPool;
|
||||
this.headerParser = new HeaderParser(rateControl == null ? RateControl.NO_RATE_CONTROL : rateControl);
|
||||
this.hpackDecoder = new HpackDecoder(maxHeaderSize, this::loadAndClearBeginNanoTime);
|
||||
this.hpackDecoder = new HpackDecoder(maxHeaderSize, this::getBeginNanoTime);
|
||||
this.bodyParsers = new BodyParser[FrameType.values().length];
|
||||
}
|
||||
|
||||
|
@ -104,16 +104,18 @@ public class Parser
|
|||
{
|
||||
headerParser.reset();
|
||||
state = State.HEADER;
|
||||
nanoTimeStored = false;
|
||||
}
|
||||
|
||||
private long loadAndClearBeginNanoTime()
|
||||
public long getBeginNanoTime()
|
||||
{
|
||||
long beginNanoTime = this.beginNanoTime;
|
||||
nanoTimeStored = false;
|
||||
return beginNanoTime;
|
||||
}
|
||||
|
||||
private void clearBeginNanoTime()
|
||||
{
|
||||
nanoTimeStored = false;
|
||||
}
|
||||
|
||||
private void storeBeginNanoTime()
|
||||
{
|
||||
if (!nanoTimeStored)
|
||||
|
@ -140,11 +142,11 @@ public class Parser
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
storeBeginNanoTime();
|
||||
switch (state)
|
||||
{
|
||||
case HEADER:
|
||||
{
|
||||
storeBeginNanoTime();
|
||||
if (!parseHeader(buffer))
|
||||
return;
|
||||
break;
|
||||
|
@ -153,6 +155,8 @@ public class Parser
|
|||
{
|
||||
if (!parseBody(buffer))
|
||||
return;
|
||||
if (!continuation)
|
||||
clearBeginNanoTime();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -161,6 +161,107 @@ public class ContinuationParseTest
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeginNanoTime() throws Exception
|
||||
{
|
||||
ArrayByteBufferPool.Tracking bufferPool = new ArrayByteBufferPool.Tracking();
|
||||
HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(bufferPool), new HpackEncoder());
|
||||
|
||||
final List<HeadersFrame> frames = new ArrayList<>();
|
||||
Parser parser = new Parser(bufferPool, 8192);
|
||||
parser.init(new Parser.Listener()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(HeadersFrame frame)
|
||||
{
|
||||
frames.add(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailure(int error, String reason)
|
||||
{
|
||||
frames.add(new HeadersFrame(null, null, false));
|
||||
}
|
||||
});
|
||||
|
||||
int streamId = 13;
|
||||
HttpFields fields = HttpFields.build()
|
||||
.put("Accept", "text/html")
|
||||
.put("User-Agent", "Jetty");
|
||||
MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1);
|
||||
|
||||
ByteBufferPool.Accumulator accumulator = new ByteBufferPool.Accumulator();
|
||||
generator.generateHeaders(accumulator, streamId, metaData, null, true);
|
||||
|
||||
List<ByteBuffer> byteBuffers = accumulator.getByteBuffers();
|
||||
assertEquals(2, byteBuffers.size());
|
||||
|
||||
ByteBuffer headersBody = byteBuffers.remove(1);
|
||||
int start = headersBody.position();
|
||||
int length = headersBody.remaining();
|
||||
int firstHalf = length / 2;
|
||||
int lastHalf = length - firstHalf;
|
||||
|
||||
// Adjust the length of the HEADERS frame.
|
||||
ByteBuffer headersHeader = byteBuffers.get(0);
|
||||
headersHeader.put(0, (byte)((firstHalf >>> 16) & 0xFF));
|
||||
headersHeader.put(1, (byte)((firstHalf >>> 8) & 0xFF));
|
||||
headersHeader.put(2, (byte)(firstHalf & 0xFF));
|
||||
|
||||
// Remove the END_HEADERS flag from the HEADERS header.
|
||||
headersHeader.put(4, (byte)(headersHeader.get(4) & ~Flags.END_HEADERS));
|
||||
|
||||
// New HEADERS body.
|
||||
headersBody.position(start);
|
||||
headersBody.limit(start + firstHalf);
|
||||
byteBuffers.add(headersBody.slice());
|
||||
|
||||
// Split the rest of the HEADERS body into a CONTINUATION frame.
|
||||
byte[] continuationHeader = new byte[9];
|
||||
continuationHeader[0] = (byte)((lastHalf >>> 16) & 0xFF);
|
||||
continuationHeader[1] = (byte)((lastHalf >>> 8) & 0xFF);
|
||||
continuationHeader[2] = (byte)(lastHalf & 0xFF);
|
||||
continuationHeader[3] = (byte)FrameType.CONTINUATION.getType();
|
||||
continuationHeader[4] = Flags.END_HEADERS;
|
||||
continuationHeader[5] = 0x00;
|
||||
continuationHeader[6] = 0x00;
|
||||
continuationHeader[7] = 0x00;
|
||||
continuationHeader[8] = (byte)streamId;
|
||||
byteBuffers.add(ByteBuffer.wrap(continuationHeader));
|
||||
// CONTINUATION body.
|
||||
headersBody.position(start + firstHalf);
|
||||
headersBody.limit(start + length);
|
||||
byteBuffers.add(headersBody.slice());
|
||||
|
||||
byteBuffers = accumulator.getByteBuffers();
|
||||
assertEquals(4, byteBuffers.size());
|
||||
parser.parse(byteBuffers.get(0));
|
||||
long beginNanoTime = parser.getBeginNanoTime();
|
||||
parser.parse(byteBuffers.get(1));
|
||||
parser.parse(byteBuffers.get(2));
|
||||
parser.parse(byteBuffers.get(3));
|
||||
|
||||
accumulator.release();
|
||||
|
||||
assertEquals(1, frames.size());
|
||||
HeadersFrame frame = frames.get(0);
|
||||
assertEquals(streamId, frame.getStreamId());
|
||||
assertTrue(frame.isEndStream());
|
||||
MetaData.Request request = (MetaData.Request)frame.getMetaData();
|
||||
assertEquals(metaData.getMethod(), request.getMethod());
|
||||
assertEquals(metaData.getHttpURI(), request.getHttpURI());
|
||||
for (int j = 0; j < fields.size(); ++j)
|
||||
{
|
||||
HttpField field = fields.getField(j);
|
||||
assertTrue(request.getHttpFields().contains(field));
|
||||
}
|
||||
PriorityFrame priority = frame.getPriority();
|
||||
assertNull(priority);
|
||||
assertEquals(beginNanoTime, request.getBeginNanoTime());
|
||||
|
||||
assertEquals(0, bufferPool.getLeaks().size(), bufferPool.dumpLeaks());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLargeHeadersBlock() throws Exception
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue