blob: 7a1848573c757ab9c781a18324547b7a318e3ca5 [file] [log] [blame]
//
// ========================================================================
// 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.http2.hpack;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
*/
public class HpackEncoderTest
{
@Test
public void testUnknownFieldsContextManagement()
{
HpackEncoder encoder = new HpackEncoder(38*5);
HttpFields fields = new HttpFields();
HttpField[] field =
{
new HttpField("fo0","b0r"),
new HttpField("fo1","b1r"),
new HttpField("fo2","b2r"),
new HttpField("fo3","b3r"),
new HttpField("fo4","b4r"),
new HttpField("fo5","b5r"),
new HttpField("fo6","b6r"),
new HttpField("fo7","b7r"),
new HttpField("fo8","b8r"),
new HttpField("fo9","b9r"),
new HttpField("foA","bAr"),
};
// Add 4 entries
for (int i=0;i<=3;i++)
fields.add(field[i]);
// encode them
ByteBuffer buffer = BufferUtil.allocate(4096);
int pos = BufferUtil.flipToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,pos);
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// All are in the dynamic table
Assert.assertEquals(4,encoder.getHpackContext().size());
// encode exact same fields again!
BufferUtil.clearToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,0);
// All are in the dynamic table
Assert.assertEquals(4,encoder.getHpackContext().size());
// Add 4 more fields
for (int i=4;i<=7;i++)
fields.add(field[i]);
// encode
BufferUtil.clearToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,0);
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// max dynamic table size reached
Assert.assertEquals(5,encoder.getHpackContext().size());
// remove some fields
for (int i=0;i<=7;i+=2)
fields.remove(field[i].getName());
// encode
BufferUtil.clearToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,0);
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// max dynamic table size reached
Assert.assertEquals(5,encoder.getHpackContext().size());
// remove another fields
fields.remove(field[1].getName());
// encode
BufferUtil.clearToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,0);
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// max dynamic table size reached
Assert.assertEquals(5,encoder.getHpackContext().size());
// re add the field
fields.add(field[1]);
// encode
BufferUtil.clearToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,0);
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// max dynamic table size reached
Assert.assertEquals(5,encoder.getHpackContext().size());
}
@Test
public void testNeverIndexSetCookie()
{
HpackEncoder encoder = new HpackEncoder(38*5);
ByteBuffer buffer = BufferUtil.allocate(4096);
HttpFields fields = new HttpFields();
fields.put("set-cookie","some cookie value");
// encode
BufferUtil.clearToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,0);
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// empty dynamic table
Assert.assertEquals(0,encoder.getHpackContext().size());
// encode again
BufferUtil.clearToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,0);
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// empty dynamic table
Assert.assertEquals(0,encoder.getHpackContext().size());
}
@Test
public void testFieldLargerThanTable()
{
HttpFields fields = new HttpFields();
HpackEncoder encoder = new HpackEncoder(128);
ByteBuffer buffer0 = BufferUtil.allocate(4096);
int pos = BufferUtil.flipToFill(buffer0);
encoder.encode(buffer0,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer0,pos);
encoder = new HpackEncoder(128);
fields.add(new HttpField("user-agent","jetty/test"));
ByteBuffer buffer1 = BufferUtil.allocate(4096);
pos = BufferUtil.flipToFill(buffer1);
encoder.encode(buffer1,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer1,pos);
encoder = new HpackEncoder(128);
fields.add(new HttpField(":path",
"This is a very large field, whose size is larger than the dynamic table so it should not be indexed as it will not fit in the table ever!"+
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "+
"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY "+
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ "));
ByteBuffer buffer2 = BufferUtil.allocate(4096);
pos = BufferUtil.flipToFill(buffer2);
encoder.encode(buffer2,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer2,pos);
encoder = new HpackEncoder(128);
fields.add(new HttpField("host","somehost"));
ByteBuffer buffer = BufferUtil.allocate(4096);
pos = BufferUtil.flipToFill(buffer);
encoder.encode(buffer,new MetaData(HttpVersion.HTTP_2,fields));
BufferUtil.flipToFlush(buffer,pos);
//System.err.println(BufferUtil.toHexString(buffer0));
//System.err.println(BufferUtil.toHexString(buffer1));
//System.err.println(BufferUtil.toHexString(buffer2));
//System.err.println(BufferUtil.toHexString(buffer));
// something was encoded!
assertThat(buffer.remaining(),Matchers.greaterThan(0));
// check first field is static index name and dynamic index body
assertThat((buffer.get(buffer0.remaining())&0xFF)>>6,equalTo(1));
// check first field is static index name and literal body
assertThat((buffer.get(buffer1.remaining())&0xFF)>>4,equalTo(0));
// check first field is static index name and dynamic index body
assertThat((buffer.get(buffer2.remaining())&0xFF)>>6,equalTo(1));
// Only first and third fields are put in the table
HpackContext context = encoder.getHpackContext();
assertThat(context.size(),equalTo(2));
assertThat(context.get(HpackContext.STATIC_SIZE+1).getHttpField().getName(),equalTo("host"));
assertThat(context.get(HpackContext.STATIC_SIZE+2).getHttpField().getName(),equalTo("user-agent"));
assertThat(context.getDynamicTableSize(),equalTo(
context.get(HpackContext.STATIC_SIZE+1).getSize()+context.get(HpackContext.STATIC_SIZE+2).getSize()));
}
}