Home | History | Annotate | Download | only in hpack
      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package hpack
      6 
      7 import (
      8 	"bytes"
      9 	"encoding/hex"
     10 	"fmt"
     11 	"math/rand"
     12 	"reflect"
     13 	"strings"
     14 	"testing"
     15 	"time"
     16 )
     17 
     18 func (d *Decoder) mustAt(idx int) HeaderField {
     19 	if hf, ok := d.at(uint64(idx)); !ok {
     20 		panic(fmt.Sprintf("bogus index %d", idx))
     21 	} else {
     22 		return hf
     23 	}
     24 }
     25 
     26 func TestDynamicTableAt(t *testing.T) {
     27 	d := NewDecoder(4096, nil)
     28 	at := d.mustAt
     29 	if got, want := at(2), (pair(":method", "GET")); got != want {
     30 		t.Errorf("at(2) = %v; want %v", got, want)
     31 	}
     32 	d.dynTab.add(pair("foo", "bar"))
     33 	d.dynTab.add(pair("blake", "miz"))
     34 	if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want {
     35 		t.Errorf("at(dyn 1) = %v; want %v", got, want)
     36 	}
     37 	if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want {
     38 		t.Errorf("at(dyn 2) = %v; want %v", got, want)
     39 	}
     40 	if got, want := at(3), (pair(":method", "POST")); got != want {
     41 		t.Errorf("at(3) = %v; want %v", got, want)
     42 	}
     43 }
     44 
     45 func TestDynamicTableSizeEvict(t *testing.T) {
     46 	d := NewDecoder(4096, nil)
     47 	if want := uint32(0); d.dynTab.size != want {
     48 		t.Fatalf("size = %d; want %d", d.dynTab.size, want)
     49 	}
     50 	add := d.dynTab.add
     51 	add(pair("blake", "eats pizza"))
     52 	if want := uint32(15 + 32); d.dynTab.size != want {
     53 		t.Fatalf("after pizza, size = %d; want %d", d.dynTab.size, want)
     54 	}
     55 	add(pair("foo", "bar"))
     56 	if want := uint32(15 + 32 + 6 + 32); d.dynTab.size != want {
     57 		t.Fatalf("after foo bar, size = %d; want %d", d.dynTab.size, want)
     58 	}
     59 	d.dynTab.setMaxSize(15 + 32 + 1 /* slop */)
     60 	if want := uint32(6 + 32); d.dynTab.size != want {
     61 		t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
     62 	}
     63 	if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want {
     64 		t.Errorf("at(dyn 1) = %v; want %v", got, want)
     65 	}
     66 	add(pair("long", strings.Repeat("x", 500)))
     67 	if want := uint32(0); d.dynTab.size != want {
     68 		t.Fatalf("after big one, size = %d; want %d", d.dynTab.size, want)
     69 	}
     70 }
     71 
     72 func TestDecoderDecode(t *testing.T) {
     73 	tests := []struct {
     74 		name       string
     75 		in         []byte
     76 		want       []HeaderField
     77 		wantDynTab []HeaderField // newest entry first
     78 	}{
     79 		// C.2.1 Literal Header Field with Indexing
     80 		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.1
     81 		{"C.2.1", dehex("400a 6375 7374 6f6d 2d6b 6579 0d63 7573 746f 6d2d 6865 6164 6572"),
     82 			[]HeaderField{pair("custom-key", "custom-header")},
     83 			[]HeaderField{pair("custom-key", "custom-header")},
     84 		},
     85 
     86 		// C.2.2 Literal Header Field without Indexing
     87 		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.2
     88 		{"C.2.2", dehex("040c 2f73 616d 706c 652f 7061 7468"),
     89 			[]HeaderField{pair(":path", "/sample/path")},
     90 			[]HeaderField{}},
     91 
     92 		// C.2.3 Literal Header Field never Indexed
     93 		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.3
     94 		{"C.2.3", dehex("1008 7061 7373 776f 7264 0673 6563 7265 74"),
     95 			[]HeaderField{{"password", "secret", true}},
     96 			[]HeaderField{}},
     97 
     98 		// C.2.4 Indexed Header Field
     99 		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.4
    100 		{"C.2.4", []byte("\x82"),
    101 			[]HeaderField{pair(":method", "GET")},
    102 			[]HeaderField{}},
    103 	}
    104 	for _, tt := range tests {
    105 		d := NewDecoder(4096, nil)
    106 		hf, err := d.DecodeFull(tt.in)
    107 		if err != nil {
    108 			t.Errorf("%s: %v", tt.name, err)
    109 			continue
    110 		}
    111 		if !reflect.DeepEqual(hf, tt.want) {
    112 			t.Errorf("%s: Got %v; want %v", tt.name, hf, tt.want)
    113 		}
    114 		gotDynTab := d.dynTab.reverseCopy()
    115 		if !reflect.DeepEqual(gotDynTab, tt.wantDynTab) {
    116 			t.Errorf("%s: dynamic table after = %v; want %v", tt.name, gotDynTab, tt.wantDynTab)
    117 		}
    118 	}
    119 }
    120 
    121 func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
    122 	hf = make([]HeaderField, len(dt.table.ents))
    123 	for i := range hf {
    124 		hf[i] = dt.table.ents[len(dt.table.ents)-1-i]
    125 	}
    126 	return
    127 }
    128 
    129 type encAndWant struct {
    130 	enc         []byte
    131 	want        []HeaderField
    132 	wantDynTab  []HeaderField
    133 	wantDynSize uint32
    134 }
    135 
    136 // C.3 Request Examples without Huffman Coding
    137 // http://http2.github.io/http2-spec/compression.html#rfc.section.C.3
    138 func TestDecodeC3_NoHuffman(t *testing.T) {
    139 	testDecodeSeries(t, 4096, []encAndWant{
    140 		{dehex("8286 8441 0f77 7777 2e65 7861 6d70 6c65 2e63 6f6d"),
    141 			[]HeaderField{
    142 				pair(":method", "GET"),
    143 				pair(":scheme", "http"),
    144 				pair(":path", "/"),
    145 				pair(":authority", "www.example.com"),
    146 			},
    147 			[]HeaderField{
    148 				pair(":authority", "www.example.com"),
    149 			},
    150 			57,
    151 		},
    152 		{dehex("8286 84be 5808 6e6f 2d63 6163 6865"),
    153 			[]HeaderField{
    154 				pair(":method", "GET"),
    155 				pair(":scheme", "http"),
    156 				pair(":path", "/"),
    157 				pair(":authority", "www.example.com"),
    158 				pair("cache-control", "no-cache"),
    159 			},
    160 			[]HeaderField{
    161 				pair("cache-control", "no-cache"),
    162 				pair(":authority", "www.example.com"),
    163 			},
    164 			110,
    165 		},
    166 		{dehex("8287 85bf 400a 6375 7374 6f6d 2d6b 6579 0c63 7573 746f 6d2d 7661 6c75 65"),
    167 			[]HeaderField{
    168 				pair(":method", "GET"),
    169 				pair(":scheme", "https"),
    170 				pair(":path", "/index.html"),
    171 				pair(":authority", "www.example.com"),
    172 				pair("custom-key", "custom-value"),
    173 			},
    174 			[]HeaderField{
    175 				pair("custom-key", "custom-value"),
    176 				pair("cache-control", "no-cache"),
    177 				pair(":authority", "www.example.com"),
    178 			},
    179 			164,
    180 		},
    181 	})
    182 }
    183 
    184 // C.4 Request Examples with Huffman Coding
    185 // http://http2.github.io/http2-spec/compression.html#rfc.section.C.4
    186 func TestDecodeC4_Huffman(t *testing.T) {
    187 	testDecodeSeries(t, 4096, []encAndWant{
    188 		{dehex("8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff"),
    189 			[]HeaderField{
    190 				pair(":method", "GET"),
    191 				pair(":scheme", "http"),
    192 				pair(":path", "/"),
    193 				pair(":authority", "www.example.com"),
    194 			},
    195 			[]HeaderField{
    196 				pair(":authority", "www.example.com"),
    197 			},
    198 			57,
    199 		},
    200 		{dehex("8286 84be 5886 a8eb 1064 9cbf"),
    201 			[]HeaderField{
    202 				pair(":method", "GET"),
    203 				pair(":scheme", "http"),
    204 				pair(":path", "/"),
    205 				pair(":authority", "www.example.com"),
    206 				pair("cache-control", "no-cache"),
    207 			},
    208 			[]HeaderField{
    209 				pair("cache-control", "no-cache"),
    210 				pair(":authority", "www.example.com"),
    211 			},
    212 			110,
    213 		},
    214 		{dehex("8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 a849 e95b b8e8 b4bf"),
    215 			[]HeaderField{
    216 				pair(":method", "GET"),
    217 				pair(":scheme", "https"),
    218 				pair(":path", "/index.html"),
    219 				pair(":authority", "www.example.com"),
    220 				pair("custom-key", "custom-value"),
    221 			},
    222 			[]HeaderField{
    223 				pair("custom-key", "custom-value"),
    224 				pair("cache-control", "no-cache"),
    225 				pair(":authority", "www.example.com"),
    226 			},
    227 			164,
    228 		},
    229 	})
    230 }
    231 
    232 // http://http2.github.io/http2-spec/compression.html#rfc.section.C.5
    233 // "This section shows several consecutive header lists, corresponding
    234 // to HTTP responses, on the same connection. The HTTP/2 setting
    235 // parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
    236 // octets, causing some evictions to occur."
    237 func TestDecodeC5_ResponsesNoHuff(t *testing.T) {
    238 	testDecodeSeries(t, 256, []encAndWant{
    239 		{dehex(`
    240 4803 3330 3258 0770 7269 7661 7465 611d
    241 4d6f 6e2c 2032 3120 4f63 7420 3230 3133
    242 2032 303a 3133 3a32 3120 474d 546e 1768
    243 7474 7073 3a2f 2f77 7777 2e65 7861 6d70
    244 6c65 2e63 6f6d
    245 `),
    246 			[]HeaderField{
    247 				pair(":status", "302"),
    248 				pair("cache-control", "private"),
    249 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    250 				pair("location", "https://www.example.com"),
    251 			},
    252 			[]HeaderField{
    253 				pair("location", "https://www.example.com"),
    254 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    255 				pair("cache-control", "private"),
    256 				pair(":status", "302"),
    257 			},
    258 			222,
    259 		},
    260 		{dehex("4803 3330 37c1 c0bf"),
    261 			[]HeaderField{
    262 				pair(":status", "307"),
    263 				pair("cache-control", "private"),
    264 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    265 				pair("location", "https://www.example.com"),
    266 			},
    267 			[]HeaderField{
    268 				pair(":status", "307"),
    269 				pair("location", "https://www.example.com"),
    270 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    271 				pair("cache-control", "private"),
    272 			},
    273 			222,
    274 		},
    275 		{dehex(`
    276 88c1 611d 4d6f 6e2c 2032 3120 4f63 7420
    277 3230 3133 2032 303a 3133 3a32 3220 474d
    278 54c0 5a04 677a 6970 7738 666f 6f3d 4153
    279 444a 4b48 514b 425a 584f 5157 454f 5049
    280 5541 5851 5745 4f49 553b 206d 6178 2d61
    281 6765 3d33 3630 303b 2076 6572 7369 6f6e
    282 3d31
    283 `),
    284 			[]HeaderField{
    285 				pair(":status", "200"),
    286 				pair("cache-control", "private"),
    287 				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
    288 				pair("location", "https://www.example.com"),
    289 				pair("content-encoding", "gzip"),
    290 				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
    291 			},
    292 			[]HeaderField{
    293 				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
    294 				pair("content-encoding", "gzip"),
    295 				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
    296 			},
    297 			215,
    298 		},
    299 	})
    300 }
    301 
    302 // http://http2.github.io/http2-spec/compression.html#rfc.section.C.6
    303 // "This section shows the same examples as the previous section, but
    304 // using Huffman encoding for the literal values. The HTTP/2 setting
    305 // parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
    306 // octets, causing some evictions to occur. The eviction mechanism
    307 // uses the length of the decoded literal values, so the same
    308 // evictions occurs as in the previous section."
    309 func TestDecodeC6_ResponsesHuffman(t *testing.T) {
    310 	testDecodeSeries(t, 256, []encAndWant{
    311 		{dehex(`
    312 4882 6402 5885 aec3 771a 4b61 96d0 7abe
    313 9410 54d4 44a8 2005 9504 0b81 66e0 82a6
    314 2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8
    315 e9ae 82ae 43d3
    316 `),
    317 			[]HeaderField{
    318 				pair(":status", "302"),
    319 				pair("cache-control", "private"),
    320 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    321 				pair("location", "https://www.example.com"),
    322 			},
    323 			[]HeaderField{
    324 				pair("location", "https://www.example.com"),
    325 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    326 				pair("cache-control", "private"),
    327 				pair(":status", "302"),
    328 			},
    329 			222,
    330 		},
    331 		{dehex("4883 640e ffc1 c0bf"),
    332 			[]HeaderField{
    333 				pair(":status", "307"),
    334 				pair("cache-control", "private"),
    335 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    336 				pair("location", "https://www.example.com"),
    337 			},
    338 			[]HeaderField{
    339 				pair(":status", "307"),
    340 				pair("location", "https://www.example.com"),
    341 				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
    342 				pair("cache-control", "private"),
    343 			},
    344 			222,
    345 		},
    346 		{dehex(`
    347 88c1 6196 d07a be94 1054 d444 a820 0595
    348 040b 8166 e084 a62d 1bff c05a 839b d9ab
    349 77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b
    350 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f
    351 9587 3160 65c0 03ed 4ee5 b106 3d50 07
    352 `),
    353 			[]HeaderField{
    354 				pair(":status", "200"),
    355 				pair("cache-control", "private"),
    356 				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
    357 				pair("location", "https://www.example.com"),
    358 				pair("content-encoding", "gzip"),
    359 				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
    360 			},
    361 			[]HeaderField{
    362 				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
    363 				pair("content-encoding", "gzip"),
    364 				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
    365 			},
    366 			215,
    367 		},
    368 	})
    369 }
    370 
    371 func testDecodeSeries(t *testing.T, size uint32, steps []encAndWant) {
    372 	d := NewDecoder(size, nil)
    373 	for i, step := range steps {
    374 		hf, err := d.DecodeFull(step.enc)
    375 		if err != nil {
    376 			t.Fatalf("Error at step index %d: %v", i, err)
    377 		}
    378 		if !reflect.DeepEqual(hf, step.want) {
    379 			t.Fatalf("At step index %d: Got headers %v; want %v", i, hf, step.want)
    380 		}
    381 		gotDynTab := d.dynTab.reverseCopy()
    382 		if !reflect.DeepEqual(gotDynTab, step.wantDynTab) {
    383 			t.Errorf("After step index %d, dynamic table = %v; want %v", i, gotDynTab, step.wantDynTab)
    384 		}
    385 		if d.dynTab.size != step.wantDynSize {
    386 			t.Errorf("After step index %d, dynamic table size = %v; want %v", i, d.dynTab.size, step.wantDynSize)
    387 		}
    388 	}
    389 }
    390 
    391 func TestHuffmanDecodeExcessPadding(t *testing.T) {
    392 	tests := [][]byte{
    393 		{0xff},                                   // Padding Exceeds 7 bits
    394 		{0x1f, 0xff},                             // {"a", 1 byte excess padding}
    395 		{0x1f, 0xff, 0xff},                       // {"a", 2 byte excess padding}
    396 		{0x1f, 0xff, 0xff, 0xff},                 // {"a", 3 byte excess padding}
    397 		{0xff, 0x9f, 0xff, 0xff, 0xff},           // {"a", 29 bit excess padding}
    398 		{'R', 0xbc, '0', 0xff, 0xff, 0xff, 0xff}, // Padding ends on partial symbol.
    399 	}
    400 	for i, in := range tests {
    401 		var buf bytes.Buffer
    402 		if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
    403 			t.Errorf("test-%d: decode(%q) = %v; want ErrInvalidHuffman", i, in, err)
    404 		}
    405 	}
    406 }
    407 
    408 func TestHuffmanDecodeEOS(t *testing.T) {
    409 	in := []byte{0xff, 0xff, 0xff, 0xff, 0xfc} // {EOS, "?"}
    410 	var buf bytes.Buffer
    411 	if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
    412 		t.Errorf("error = %v; want ErrInvalidHuffman", err)
    413 	}
    414 }
    415 
    416 func TestHuffmanDecodeMaxLengthOnTrailingByte(t *testing.T) {
    417 	in := []byte{0x00, 0x01} // {"0", "0", "0"}
    418 	var buf bytes.Buffer
    419 	if err := huffmanDecode(&buf, 2, in); err != ErrStringLength {
    420 		t.Errorf("error = %v; want ErrStringLength", err)
    421 	}
    422 }
    423 
    424 func TestHuffmanDecodeCorruptPadding(t *testing.T) {
    425 	in := []byte{0x00}
    426 	var buf bytes.Buffer
    427 	if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman {
    428 		t.Errorf("error = %v; want ErrInvalidHuffman", err)
    429 	}
    430 }
    431 
    432 func TestHuffmanDecode(t *testing.T) {
    433 	tests := []struct {
    434 		inHex, want string
    435 	}{
    436 		{"f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"},
    437 		{"a8eb 1064 9cbf", "no-cache"},
    438 		{"25a8 49e9 5ba9 7d7f", "custom-key"},
    439 		{"25a8 49e9 5bb8 e8b4 bf", "custom-value"},
    440 		{"6402", "302"},
    441 		{"aec3 771a 4b", "private"},
    442 		{"d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", "Mon, 21 Oct 2013 20:13:21 GMT"},
    443 		{"9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", "https://www.example.com"},
    444 		{"9bd9 ab", "gzip"},
    445 		{"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07",
    446 			"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
    447 	}
    448 	for i, tt := range tests {
    449 		var buf bytes.Buffer
    450 		in, err := hex.DecodeString(strings.Replace(tt.inHex, " ", "", -1))
    451 		if err != nil {
    452 			t.Errorf("%d. hex input error: %v", i, err)
    453 			continue
    454 		}
    455 		if _, err := HuffmanDecode(&buf, in); err != nil {
    456 			t.Errorf("%d. decode error: %v", i, err)
    457 			continue
    458 		}
    459 		if got := buf.String(); tt.want != got {
    460 			t.Errorf("%d. decode = %q; want %q", i, got, tt.want)
    461 		}
    462 	}
    463 }
    464 
    465 func TestAppendHuffmanString(t *testing.T) {
    466 	tests := []struct {
    467 		in, want string
    468 	}{
    469 		{"www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
    470 		{"no-cache", "a8eb 1064 9cbf"},
    471 		{"custom-key", "25a8 49e9 5ba9 7d7f"},
    472 		{"custom-value", "25a8 49e9 5bb8 e8b4 bf"},
    473 		{"302", "6402"},
    474 		{"private", "aec3 771a 4b"},
    475 		{"Mon, 21 Oct 2013 20:13:21 GMT", "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"},
    476 		{"https://www.example.com", "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"},
    477 		{"gzip", "9bd9 ab"},
    478 		{"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
    479 			"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07"},
    480 	}
    481 	for i, tt := range tests {
    482 		buf := []byte{}
    483 		want := strings.Replace(tt.want, " ", "", -1)
    484 		buf = AppendHuffmanString(buf, tt.in)
    485 		if got := hex.EncodeToString(buf); want != got {
    486 			t.Errorf("%d. encode = %q; want %q", i, got, want)
    487 		}
    488 	}
    489 }
    490 
    491 func TestHuffmanMaxStrLen(t *testing.T) {
    492 	const msg = "Some string"
    493 	huff := AppendHuffmanString(nil, msg)
    494 
    495 	testGood := func(max int) {
    496 		var out bytes.Buffer
    497 		if err := huffmanDecode(&out, max, huff); err != nil {
    498 			t.Errorf("For maxLen=%d, unexpected error: %v", max, err)
    499 		}
    500 		if out.String() != msg {
    501 			t.Errorf("For maxLen=%d, out = %q; want %q", max, out.String(), msg)
    502 		}
    503 	}
    504 	testGood(0)
    505 	testGood(len(msg))
    506 	testGood(len(msg) + 1)
    507 
    508 	var out bytes.Buffer
    509 	if err := huffmanDecode(&out, len(msg)-1, huff); err != ErrStringLength {
    510 		t.Errorf("err = %v; want ErrStringLength", err)
    511 	}
    512 }
    513 
    514 func TestHuffmanRoundtripStress(t *testing.T) {
    515 	const Len = 50 // of uncompressed string
    516 	input := make([]byte, Len)
    517 	var output bytes.Buffer
    518 	var huff []byte
    519 
    520 	n := 5000
    521 	if testing.Short() {
    522 		n = 100
    523 	}
    524 	seed := time.Now().UnixNano()
    525 	t.Logf("Seed = %v", seed)
    526 	src := rand.New(rand.NewSource(seed))
    527 	var encSize int64
    528 	for i := 0; i < n; i++ {
    529 		for l := range input {
    530 			input[l] = byte(src.Intn(256))
    531 		}
    532 		huff = AppendHuffmanString(huff[:0], string(input))
    533 		encSize += int64(len(huff))
    534 		output.Reset()
    535 		if err := huffmanDecode(&output, 0, huff); err != nil {
    536 			t.Errorf("Failed to decode %q -> %q -> error %v", input, huff, err)
    537 			continue
    538 		}
    539 		if !bytes.Equal(output.Bytes(), input) {
    540 			t.Errorf("Roundtrip failure on %q -> %q -> %q", input, huff, output.Bytes())
    541 		}
    542 	}
    543 	t.Logf("Compressed size of original: %0.02f%% (%v -> %v)", 100*(float64(encSize)/(Len*float64(n))), Len*n, encSize)
    544 }
    545 
    546 func TestHuffmanDecodeFuzz(t *testing.T) {
    547 	const Len = 50 // of compressed
    548 	var buf, zbuf bytes.Buffer
    549 
    550 	n := 5000
    551 	if testing.Short() {
    552 		n = 100
    553 	}
    554 	seed := time.Now().UnixNano()
    555 	t.Logf("Seed = %v", seed)
    556 	src := rand.New(rand.NewSource(seed))
    557 	numFail := 0
    558 	for i := 0; i < n; i++ {
    559 		zbuf.Reset()
    560 		if i == 0 {
    561 			// Start with at least one invalid one.
    562 			zbuf.WriteString("00\x91\xff\xff\xff\xff\xc8")
    563 		} else {
    564 			for l := 0; l < Len; l++ {
    565 				zbuf.WriteByte(byte(src.Intn(256)))
    566 			}
    567 		}
    568 
    569 		buf.Reset()
    570 		if err := huffmanDecode(&buf, 0, zbuf.Bytes()); err != nil {
    571 			if err == ErrInvalidHuffman {
    572 				numFail++
    573 				continue
    574 			}
    575 			t.Errorf("Failed to decode %q: %v", zbuf.Bytes(), err)
    576 			continue
    577 		}
    578 	}
    579 	t.Logf("%0.02f%% are invalid (%d / %d)", 100*float64(numFail)/float64(n), numFail, n)
    580 	if numFail < 1 {
    581 		t.Error("expected at least one invalid huffman encoding (test starts with one)")
    582 	}
    583 }
    584 
    585 func TestReadVarInt(t *testing.T) {
    586 	type res struct {
    587 		i        uint64
    588 		consumed int
    589 		err      error
    590 	}
    591 	tests := []struct {
    592 		n    byte
    593 		p    []byte
    594 		want res
    595 	}{
    596 		// Fits in a byte:
    597 		{1, []byte{0}, res{0, 1, nil}},
    598 		{2, []byte{2}, res{2, 1, nil}},
    599 		{3, []byte{6}, res{6, 1, nil}},
    600 		{4, []byte{14}, res{14, 1, nil}},
    601 		{5, []byte{30}, res{30, 1, nil}},
    602 		{6, []byte{62}, res{62, 1, nil}},
    603 		{7, []byte{126}, res{126, 1, nil}},
    604 		{8, []byte{254}, res{254, 1, nil}},
    605 
    606 		// Doesn't fit in a byte:
    607 		{1, []byte{1}, res{0, 0, errNeedMore}},
    608 		{2, []byte{3}, res{0, 0, errNeedMore}},
    609 		{3, []byte{7}, res{0, 0, errNeedMore}},
    610 		{4, []byte{15}, res{0, 0, errNeedMore}},
    611 		{5, []byte{31}, res{0, 0, errNeedMore}},
    612 		{6, []byte{63}, res{0, 0, errNeedMore}},
    613 		{7, []byte{127}, res{0, 0, errNeedMore}},
    614 		{8, []byte{255}, res{0, 0, errNeedMore}},
    615 
    616 		// Ignoring top bits:
    617 		{5, []byte{255, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 111
    618 		{5, []byte{159, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 100
    619 		{5, []byte{191, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 101
    620 
    621 		// Extra byte:
    622 		{5, []byte{191, 154, 10, 2}, res{1337, 3, nil}}, // extra byte
    623 
    624 		// Short a byte:
    625 		{5, []byte{191, 154}, res{0, 0, errNeedMore}},
    626 
    627 		// integer overflow:
    628 		{1, []byte{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, res{0, 0, errVarintOverflow}},
    629 	}
    630 	for _, tt := range tests {
    631 		i, remain, err := readVarInt(tt.n, tt.p)
    632 		consumed := len(tt.p) - len(remain)
    633 		got := res{i, consumed, err}
    634 		if got != tt.want {
    635 			t.Errorf("readVarInt(%d, %v ~ %x) = %+v; want %+v", tt.n, tt.p, tt.p, got, tt.want)
    636 		}
    637 	}
    638 }
    639 
    640 // Fuzz crash, originally reported at https://github.com/bradfitz/http2/issues/56
    641 func TestHuffmanFuzzCrash(t *testing.T) {
    642 	got, err := HuffmanDecodeToString([]byte("00\x91\xff\xff\xff\xff\xc8"))
    643 	if got != "" {
    644 		t.Errorf("Got %q; want empty string", got)
    645 	}
    646 	if err != ErrInvalidHuffman {
    647 		t.Errorf("Err = %v; want ErrInvalidHuffman", err)
    648 	}
    649 }
    650 
    651 func pair(name, value string) HeaderField {
    652 	return HeaderField{Name: name, Value: value}
    653 }
    654 
    655 func dehex(s string) []byte {
    656 	s = strings.Replace(s, " ", "", -1)
    657 	s = strings.Replace(s, "\n", "", -1)
    658 	b, err := hex.DecodeString(s)
    659 	if err != nil {
    660 		panic(err)
    661 	}
    662 	return b
    663 }
    664 
    665 func TestEmitEnabled(t *testing.T) {
    666 	var buf bytes.Buffer
    667 	enc := NewEncoder(&buf)
    668 	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
    669 	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
    670 
    671 	numCallback := 0
    672 	var dec *Decoder
    673 	dec = NewDecoder(8<<20, func(HeaderField) {
    674 		numCallback++
    675 		dec.SetEmitEnabled(false)
    676 	})
    677 	if !dec.EmitEnabled() {
    678 		t.Errorf("initial emit enabled = false; want true")
    679 	}
    680 	if _, err := dec.Write(buf.Bytes()); err != nil {
    681 		t.Error(err)
    682 	}
    683 	if numCallback != 1 {
    684 		t.Errorf("num callbacks = %d; want 1", numCallback)
    685 	}
    686 	if dec.EmitEnabled() {
    687 		t.Errorf("emit enabled = true; want false")
    688 	}
    689 }
    690 
    691 func TestSaveBufLimit(t *testing.T) {
    692 	const maxStr = 1 << 10
    693 	var got []HeaderField
    694 	dec := NewDecoder(initialHeaderTableSize, func(hf HeaderField) {
    695 		got = append(got, hf)
    696 	})
    697 	dec.SetMaxStringLength(maxStr)
    698 	var frag []byte
    699 	frag = append(frag[:0], encodeTypeByte(false, false))
    700 	frag = appendVarInt(frag, 7, 3)
    701 	frag = append(frag, "foo"...)
    702 	frag = appendVarInt(frag, 7, 3)
    703 	frag = append(frag, "bar"...)
    704 
    705 	if _, err := dec.Write(frag); err != nil {
    706 		t.Fatal(err)
    707 	}
    708 
    709 	want := []HeaderField{{Name: "foo", Value: "bar"}}
    710 	if !reflect.DeepEqual(got, want) {
    711 		t.Errorf("After small writes, got %v; want %v", got, want)
    712 	}
    713 
    714 	frag = append(frag[:0], encodeTypeByte(false, false))
    715 	frag = appendVarInt(frag, 7, maxStr*3)
    716 	frag = append(frag, make([]byte, maxStr*3)...)
    717 
    718 	_, err := dec.Write(frag)
    719 	if err != ErrStringLength {
    720 		t.Fatalf("Write error = %v; want ErrStringLength", err)
    721 	}
    722 }
    723