func TestDecodeC4_Huffman(t *testing.T) {
	testDecodeSeries(t, 4096, []encAndWant{
		{dehex("8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff"),
			[]HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "http"),
				pair(":path", "/"),
				pair(":authority", "www.example.com"),
			},
			[]HeaderField{
				pair(":authority", "www.example.com"),
			},
			57,
		},
		{dehex("8286 84be 5886 a8eb 1064 9cbf"),
			[]HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "http"),
				pair(":path", "/"),
				pair(":authority", "www.example.com"),
				pair("cache-control", "no-cache"),
			},
			[]HeaderField{
				pair("cache-control", "no-cache"),
				pair(":authority", "www.example.com"),
			},
			110,
		},
		{dehex("8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 a849 e95b b8e8 b4bf"),
			[]HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "https"),
				pair(":path", "/index.html"),
				pair(":authority", "www.example.com"),
				pair("custom-key", "custom-value"),
			},
			[]HeaderField{
				pair("custom-key", "custom-value"),
				pair("cache-control", "no-cache"),
				pair(":authority", "www.example.com"),
			},
			164,
		},
	})
}
C.4 Request Examples with Huffman Coding
http://http2.github.io/http2-spec/compression.html#rfc.section.C.4
package hpack
import (
	"bytes"
	"encoding/hex"
	"fmt"
	"math/rand"
	"reflect"
	"strings"
	"testing"
	"time"
)
func (d *Decoder) mustAt(idx int) HeaderField {
	if hf, ok := d.at(uint64(idx)); !ok {
		panic(fmt.Sprintf("bogus index %d", idx))
	} else {
		return hf
	}
}
func TestDynamicTableAt(t *testing.T) {
	d := NewDecoder(4096, nil)
	at := d.mustAt
	if got, want := at(2), (pair(":method", "GET")); got != want {
		t.Errorf("at(2) = %v; want %v", got, want)
	}
	d.dynTab.add(pair("foo", "bar"))
	d.dynTab.add(pair("blake", "miz"))
	if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want {
		t.Errorf("at(dyn 1) = %v; want %v", got, want)
	}
	if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want {
		t.Errorf("at(dyn 2) = %v; want %v", got, want)
	}
	if got, want := at(3), (pair(":method", "POST")); got != want {
		t.Errorf("at(3) = %v; want %v", got, want)
	}
}
func TestDynamicTableSizeEvict(t *testing.T) {
	d := NewDecoder(4096, nil)
	if want := uint32(0); d.dynTab.size != want {
		t.Fatalf("size = %d; want %d", d.dynTab.size, want)
	}
	add := d.dynTab.add
	add(pair("blake", "eats pizza"))
	if want := uint32(15 + 32); d.dynTab.size != want {
		t.Fatalf("after pizza, size = %d; want %d", d.dynTab.size, want)
	}
	add(pair("foo", "bar"))
	if want := uint32(15 + 32 + 6 + 32); d.dynTab.size != want {
		t.Fatalf("after foo bar, size = %d; want %d", d.dynTab.size, want)
	}
	d.dynTab.setMaxSize(15 + 32 + 1  )
	if want := uint32(6 + 32); d.dynTab.size != want {
		t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
	}
	if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want {
		t.Errorf("at(dyn 1) = %v; want %v", got, want)
	}
	add(pair("long", strings.Repeat("x", 500)))
	if want := uint32(0); d.dynTab.size != want {
		t.Fatalf("after big one, size = %d; want %d", d.dynTab.size, want)
	}
}
func TestDecoderDecode(t *testing.T) {
	tests := []struct {
		name       string
		in         []byte
		want       []HeaderField
		wantDynTab []HeaderField  
	}{
		{"C.2.1", dehex("400a 6375 7374 6f6d 2d6b 6579 0d63 7573 746f 6d2d 6865 6164 6572"),
			[]HeaderField{pair("custom-key", "custom-header")},
			[]HeaderField{pair("custom-key", "custom-header")},
		},
		{"C.2.2", dehex("040c 2f73 616d 706c 652f 7061 7468"),
			[]HeaderField{pair(":path", "/sample/path")},
			[]HeaderField{}},
		{"C.2.3", dehex("1008 7061 7373 776f 7264 0673 6563 7265 74"),
			[]HeaderField{{"password", "secret", true}},
			[]HeaderField{}},
		{"C.2.4", []byte("\x82"),
			[]HeaderField{pair(":method", "GET")},
			[]HeaderField{}},
	}
	for _, tt := range tests {
		d := NewDecoder(4096, nil)
		hf, err := d.DecodeFull(tt.in)
		if err != nil {
			t.Errorf("%s: %v", tt.name, err)
			continue
		}
		if !reflect.DeepEqual(hf, tt.want) {
			t.Errorf("%s: Got %v; want %v", tt.name, hf, tt.want)
		}
		gotDynTab := d.dynTab.reverseCopy()
		if !reflect.DeepEqual(gotDynTab, tt.wantDynTab) {
			t.Errorf("%s: dynamic table after = %v; want %v", tt.name, gotDynTab, tt.wantDynTab)
		}
	}
}
func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
	hf = make([]HeaderField, len(dt.table.ents))
	for i := range hf {
		hf[i] = dt.table.ents[len(dt.table.ents)-1-i]
	}
	return
}
type encAndWant struct {
	enc         []byte
	want        []HeaderField
	wantDynTab  []HeaderField
	wantDynSize uint32
}
func TestDecodeC3_NoHuffman(t *testing.T) {
	testDecodeSeries(t, 4096, []encAndWant{
		{dehex("8286 8441 0f77 7777 2e65 7861 6d70 6c65 2e63 6f6d"),
			[]HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "http"),
				pair(":path", "/"),
				pair(":authority", "www.example.com"),
			},
			[]HeaderField{
				pair(":authority", "www.example.com"),
			},
			57,
		},
		{dehex("8286 84be 5808 6e6f 2d63 6163 6865"),
			[]HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "http"),
				pair(":path", "/"),
				pair(":authority", "www.example.com"),
				pair("cache-control", "no-cache"),
			},
			[]HeaderField{
				pair("cache-control", "no-cache"),
				pair(":authority", "www.example.com"),
			},
			110,
		},
		{dehex("8287 85bf 400a 6375 7374 6f6d 2d6b 6579 0c63 7573 746f 6d2d 7661 6c75 65"),
			[]HeaderField{
				pair(":method", "GET"),
				pair(":scheme", "https"),
				pair(":path", "/index.html"),
				pair(":authority", "www.example.com"),
				pair("custom-key", "custom-value"),
			},
			[]HeaderField{
				pair("custom-key", "custom-value"),
				pair("cache-control", "no-cache"),
				pair(":authority", "www.example.com"),
			},
			164,
		},
	})
}