github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/http2/hpack/hpack_test.go (about)

     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 BenchmarkHuffmanDecode(b *testing.B) {
   466  	b.StopTimer()
   467  	enc, err := hex.DecodeString(strings.Replace("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07",
   468  		" ", "", -1))
   469  	if err != nil {
   470  		b.Fatal(err)
   471  	}
   472  	b.ReportAllocs()
   473  	b.StartTimer()
   474  	var buf bytes.Buffer
   475  	for i := 0; i < b.N; i++ {
   476  		buf.Reset()
   477  		if _, err := HuffmanDecode(&buf, enc); err != nil {
   478  			b.Fatalf("decode error: %v", err)
   479  		}
   480  		if string(buf.Bytes()) != "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1" {
   481  			b.Fatalf("bogus output %q", buf.Bytes())
   482  		}
   483  	}
   484  }
   485  
   486  func TestAppendHuffmanString(t *testing.T) {
   487  	tests := []struct {
   488  		in, want string
   489  	}{
   490  		{"www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
   491  		{"no-cache", "a8eb 1064 9cbf"},
   492  		{"custom-key", "25a8 49e9 5ba9 7d7f"},
   493  		{"custom-value", "25a8 49e9 5bb8 e8b4 bf"},
   494  		{"302", "6402"},
   495  		{"private", "aec3 771a 4b"},
   496  		{"Mon, 21 Oct 2013 20:13:21 GMT", "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"},
   497  		{"https://www.example.com", "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"},
   498  		{"gzip", "9bd9 ab"},
   499  		{"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
   500  			"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07"},
   501  	}
   502  	for i, tt := range tests {
   503  		buf := []byte{}
   504  		want := strings.Replace(tt.want, " ", "", -1)
   505  		buf = AppendHuffmanString(buf, tt.in)
   506  		if got := hex.EncodeToString(buf); want != got {
   507  			t.Errorf("%d. encode = %q; want %q", i, got, want)
   508  		}
   509  	}
   510  }
   511  
   512  func TestHuffmanMaxStrLen(t *testing.T) {
   513  	const msg = "Some string"
   514  	huff := AppendHuffmanString(nil, msg)
   515  
   516  	testGood := func(max int) {
   517  		var out bytes.Buffer
   518  		if err := huffmanDecode(&out, max, huff); err != nil {
   519  			t.Errorf("For maxLen=%d, unexpected error: %v", max, err)
   520  		}
   521  		if out.String() != msg {
   522  			t.Errorf("For maxLen=%d, out = %q; want %q", max, out.String(), msg)
   523  		}
   524  	}
   525  	testGood(0)
   526  	testGood(len(msg))
   527  	testGood(len(msg) + 1)
   528  
   529  	var out bytes.Buffer
   530  	if err := huffmanDecode(&out, len(msg)-1, huff); err != ErrStringLength {
   531  		t.Errorf("err = %v; want ErrStringLength", err)
   532  	}
   533  }
   534  
   535  func TestHuffmanRoundtripStress(t *testing.T) {
   536  	const Len = 50 // of uncompressed string
   537  	input := make([]byte, Len)
   538  	var output bytes.Buffer
   539  	var huff []byte
   540  
   541  	n := 5000
   542  	if testing.Short() {
   543  		n = 100
   544  	}
   545  	seed := time.Now().UnixNano()
   546  	t.Logf("Seed = %v", seed)
   547  	src := rand.New(rand.NewSource(seed))
   548  	var encSize int64
   549  	for i := 0; i < n; i++ {
   550  		for l := range input {
   551  			input[l] = byte(src.Intn(256))
   552  		}
   553  		huff = AppendHuffmanString(huff[:0], string(input))
   554  		encSize += int64(len(huff))
   555  		output.Reset()
   556  		if err := huffmanDecode(&output, 0, huff); err != nil {
   557  			t.Errorf("Failed to decode %q -> %q -> error %v", input, huff, err)
   558  			continue
   559  		}
   560  		if !bytes.Equal(output.Bytes(), input) {
   561  			t.Errorf("Roundtrip failure on %q -> %q -> %q", input, huff, output.Bytes())
   562  		}
   563  	}
   564  	t.Logf("Compressed size of original: %0.02f%% (%v -> %v)", 100*(float64(encSize)/(Len*float64(n))), Len*n, encSize)
   565  }
   566  
   567  func TestHuffmanDecodeFuzz(t *testing.T) {
   568  	const Len = 50 // of compressed
   569  	var buf, zbuf bytes.Buffer
   570  
   571  	n := 5000
   572  	if testing.Short() {
   573  		n = 100
   574  	}
   575  	seed := time.Now().UnixNano()
   576  	t.Logf("Seed = %v", seed)
   577  	src := rand.New(rand.NewSource(seed))
   578  	numFail := 0
   579  	for i := 0; i < n; i++ {
   580  		zbuf.Reset()
   581  		if i == 0 {
   582  			// Start with at least one invalid one.
   583  			zbuf.WriteString("00\x91\xff\xff\xff\xff\xc8")
   584  		} else {
   585  			for l := 0; l < Len; l++ {
   586  				zbuf.WriteByte(byte(src.Intn(256)))
   587  			}
   588  		}
   589  
   590  		buf.Reset()
   591  		if err := huffmanDecode(&buf, 0, zbuf.Bytes()); err != nil {
   592  			if err == ErrInvalidHuffman {
   593  				numFail++
   594  				continue
   595  			}
   596  			t.Errorf("Failed to decode %q: %v", zbuf.Bytes(), err)
   597  			continue
   598  		}
   599  	}
   600  	t.Logf("%0.02f%% are invalid (%d / %d)", 100*float64(numFail)/float64(n), numFail, n)
   601  	if numFail < 1 {
   602  		t.Error("expected at least one invalid huffman encoding (test starts with one)")
   603  	}
   604  }
   605  
   606  func TestReadVarInt(t *testing.T) {
   607  	type res struct {
   608  		i        uint64
   609  		consumed int
   610  		err      error
   611  	}
   612  	tests := []struct {
   613  		n    byte
   614  		p    []byte
   615  		want res
   616  	}{
   617  		// Fits in a byte:
   618  		{1, []byte{0}, res{0, 1, nil}},
   619  		{2, []byte{2}, res{2, 1, nil}},
   620  		{3, []byte{6}, res{6, 1, nil}},
   621  		{4, []byte{14}, res{14, 1, nil}},
   622  		{5, []byte{30}, res{30, 1, nil}},
   623  		{6, []byte{62}, res{62, 1, nil}},
   624  		{7, []byte{126}, res{126, 1, nil}},
   625  		{8, []byte{254}, res{254, 1, nil}},
   626  
   627  		// Doesn't fit in a byte:
   628  		{1, []byte{1}, res{0, 0, errNeedMore}},
   629  		{2, []byte{3}, res{0, 0, errNeedMore}},
   630  		{3, []byte{7}, res{0, 0, errNeedMore}},
   631  		{4, []byte{15}, res{0, 0, errNeedMore}},
   632  		{5, []byte{31}, res{0, 0, errNeedMore}},
   633  		{6, []byte{63}, res{0, 0, errNeedMore}},
   634  		{7, []byte{127}, res{0, 0, errNeedMore}},
   635  		{8, []byte{255}, res{0, 0, errNeedMore}},
   636  
   637  		// Ignoring top bits:
   638  		{5, []byte{255, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 111
   639  		{5, []byte{159, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 100
   640  		{5, []byte{191, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 101
   641  
   642  		// Extra byte:
   643  		{5, []byte{191, 154, 10, 2}, res{1337, 3, nil}}, // extra byte
   644  
   645  		// Short a byte:
   646  		{5, []byte{191, 154}, res{0, 0, errNeedMore}},
   647  
   648  		// integer overflow:
   649  		{1, []byte{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, res{0, 0, errVarintOverflow}},
   650  	}
   651  	for _, tt := range tests {
   652  		i, remain, err := readVarInt(tt.n, tt.p)
   653  		consumed := len(tt.p) - len(remain)
   654  		got := res{i, consumed, err}
   655  		if got != tt.want {
   656  			t.Errorf("readVarInt(%d, %v ~ %x) = %+v; want %+v", tt.n, tt.p, tt.p, got, tt.want)
   657  		}
   658  	}
   659  }
   660  
   661  // Fuzz crash, originally reported at https://github.com/bradfitz/http2/issues/56
   662  func TestHuffmanFuzzCrash(t *testing.T) {
   663  	got, err := HuffmanDecodeToString([]byte("00\x91\xff\xff\xff\xff\xc8"))
   664  	if got != "" {
   665  		t.Errorf("Got %q; want empty string", got)
   666  	}
   667  	if err != ErrInvalidHuffman {
   668  		t.Errorf("Err = %v; want ErrInvalidHuffman", err)
   669  	}
   670  }
   671  
   672  func pair(name, value string) HeaderField {
   673  	return HeaderField{Name: name, Value: value}
   674  }
   675  
   676  func dehex(s string) []byte {
   677  	s = strings.Replace(s, " ", "", -1)
   678  	s = strings.Replace(s, "\n", "", -1)
   679  	b, err := hex.DecodeString(s)
   680  	if err != nil {
   681  		panic(err)
   682  	}
   683  	return b
   684  }
   685  
   686  func TestEmitEnabled(t *testing.T) {
   687  	var buf bytes.Buffer
   688  	enc := NewEncoder(&buf)
   689  	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
   690  	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
   691  
   692  	numCallback := 0
   693  	var dec *Decoder
   694  	dec = NewDecoder(8<<20, func(HeaderField) {
   695  		numCallback++
   696  		dec.SetEmitEnabled(false)
   697  	})
   698  	if !dec.EmitEnabled() {
   699  		t.Errorf("initial emit enabled = false; want true")
   700  	}
   701  	if _, err := dec.Write(buf.Bytes()); err != nil {
   702  		t.Error(err)
   703  	}
   704  	if numCallback != 1 {
   705  		t.Errorf("num callbacks = %d; want 1", numCallback)
   706  	}
   707  	if dec.EmitEnabled() {
   708  		t.Errorf("emit enabled = true; want false")
   709  	}
   710  }
   711  
   712  func TestSaveBufLimit(t *testing.T) {
   713  	const maxStr = 1 << 10
   714  	var got []HeaderField
   715  	dec := NewDecoder(initialHeaderTableSize, func(hf HeaderField) {
   716  		got = append(got, hf)
   717  	})
   718  	dec.SetMaxStringLength(maxStr)
   719  	var frag []byte
   720  	frag = append(frag[:0], encodeTypeByte(false, false))
   721  	frag = appendVarInt(frag, 7, 3)
   722  	frag = append(frag, "foo"...)
   723  	frag = appendVarInt(frag, 7, 3)
   724  	frag = append(frag, "bar"...)
   725  
   726  	if _, err := dec.Write(frag); err != nil {
   727  		t.Fatal(err)
   728  	}
   729  
   730  	want := []HeaderField{{Name: "foo", Value: "bar"}}
   731  	if !reflect.DeepEqual(got, want) {
   732  		t.Errorf("After small writes, got %v; want %v", got, want)
   733  	}
   734  
   735  	frag = append(frag[:0], encodeTypeByte(false, false))
   736  	frag = appendVarInt(frag, 7, maxStr*3)
   737  	frag = append(frag, make([]byte, maxStr*3)...)
   738  
   739  	_, err := dec.Write(frag)
   740  	if err != ErrStringLength {
   741  		t.Fatalf("Write error = %v; want ErrStringLength", err)
   742  	}
   743  }
   744  
   745  func TestDynamicSizeUpdate(t *testing.T) {
   746  	var buf bytes.Buffer
   747  	enc := NewEncoder(&buf)
   748  	enc.SetMaxDynamicTableSize(255)
   749  	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
   750  
   751  	d := NewDecoder(4096, func(_ HeaderField) {})
   752  	_, err := d.Write(buf.Bytes())
   753  	if err != nil {
   754  		t.Fatalf("unexpected error: got = %v", err)
   755  	}
   756  
   757  	d.Close()
   758  
   759  	// Start a new header
   760  	_, err = d.Write(buf.Bytes())
   761  	if err != nil {
   762  		t.Fatalf("unexpected error: got = %v", err)
   763  	}
   764  
   765  	// must fail since the dynamic table update must be at the beginning
   766  	_, err = d.Write(buf.Bytes())
   767  	if err == nil {
   768  		t.Fatalf("dynamic table size update not at the beginning of a header block")
   769  	}
   770  }