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.
16 "golang.org/x/net/http2/hpack"
19 func testFramer() (*Framer, *bytes.Buffer) {
20 buf := new(bytes.Buffer)
21 return NewFramer(buf, buf), buf
24 func TestFrameSizes(t *testing.T) {
25 // Catch people rearranging the FrameHeader fields.
26 if got, want := int(unsafe.Sizeof(FrameHeader{})), 12; got != want {
27 t.Errorf("FrameHeader size = %d; want %d", got, want)
31 func TestFrameTypeString(t *testing.T) {
38 {FrameGoAway, "GOAWAY"},
39 {0xf, "UNKNOWN_FRAME_TYPE_15"},
42 for i, tt := range tests {
45 t.Errorf("%d. String(FrameType %d) = %q; want %q", i, int(tt.ft), got, tt.want)
50 func TestWriteRST(t *testing.T) {
51 fr, buf := testFramer()
52 var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
53 var errCode uint32 = 7<<24 + 6<<16 + 5<<8 + 4
54 fr.WriteRSTStream(streamID, ErrCode(errCode))
55 const wantEnc = "\x00\x00\x04\x03\x00\x01\x02\x03\x04\x07\x06\x05\x04"
56 if buf.String() != wantEnc {
57 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
59 f, err := fr.ReadFrame()
63 want := &RSTStreamFrame{
64 FrameHeader: FrameHeader{
73 if !reflect.DeepEqual(f, want) {
74 t.Errorf("parsed back %#v; want %#v", f, want)
78 func TestWriteData(t *testing.T) {
79 fr, buf := testFramer()
80 var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
82 fr.WriteData(streamID, true, data)
83 const wantEnc = "\x00\x00\x03\x00\x01\x01\x02\x03\x04ABC"
84 if buf.String() != wantEnc {
85 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
87 f, err := fr.ReadFrame()
91 df, ok := f.(*DataFrame)
93 t.Fatalf("got %T; want *DataFrame", f)
95 if !bytes.Equal(df.Data(), data) {
96 t.Errorf("got %q; want %q", df.Data(), data)
98 if f.Header().Flags&1 == 0 {
99 t.Errorf("didn't see END_STREAM flag")
103 func TestWriteDataPadded(t *testing.T) {
104 tests := [...]struct {
109 wantHeader FrameHeader
117 wantHeader: FrameHeader{
119 Flags: FlagDataEndStream,
125 // Padded bit set, but no padding:
131 wantHeader: FrameHeader{
133 Flags: FlagDataEndStream | FlagDataPadded,
139 // Padded bit set, with padding:
144 pad: []byte{0, 0, 0},
145 wantHeader: FrameHeader{
147 Flags: FlagDataPadded,
153 for i, tt := range tests {
154 fr, _ := testFramer()
155 fr.WriteDataPadded(tt.streamID, tt.endStream, tt.data, tt.pad)
156 f, err := fr.ReadFrame()
158 t.Errorf("%d. ReadFrame: %v", i, err)
162 tt.wantHeader.valid = true
163 if got != tt.wantHeader {
164 t.Errorf("%d. read %+v; want %+v", i, got, tt.wantHeader)
168 if !bytes.Equal(df.Data(), tt.data) {
169 t.Errorf("%d. got %q; want %q", i, df.Data(), tt.data)
174 func TestWriteHeaders(t *testing.T) {
179 wantFrame *HeadersFrame
185 BlockFragment: []byte("abc"),
186 Priority: PriorityParam{},
188 "\x00\x00\x03\x01\x00\x00\x00\x00*abc",
190 FrameHeader: FrameHeader{
194 Length: uint32(len("abc")),
196 Priority: PriorityParam{},
197 headerFragBuf: []byte("abc"),
204 BlockFragment: []byte("abc"),
207 Priority: PriorityParam{},
209 "\x00\x00\x03\x01\x05\x00\x00\x00*abc",
211 FrameHeader: FrameHeader{
215 Flags: FlagHeadersEndStream | FlagHeadersEndHeaders,
216 Length: uint32(len("abc")),
218 Priority: PriorityParam{},
219 headerFragBuf: []byte("abc"),
226 BlockFragment: []byte("abc"),
230 Priority: PriorityParam{},
232 "\x00\x00\t\x01\r\x00\x00\x00*\x05abc\x00\x00\x00\x00\x00",
234 FrameHeader: FrameHeader{
238 Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded,
239 Length: uint32(1 + len("abc") + 5), // pad length + contents + padding
241 Priority: PriorityParam{},
242 headerFragBuf: []byte("abc"),
249 BlockFragment: []byte("abc"),
253 Priority: PriorityParam{
259 "\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x0f\u007fabc\x00\x00",
261 FrameHeader: FrameHeader{
265 Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
266 Length: uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
268 Priority: PriorityParam{
273 headerFragBuf: []byte("abc"),
277 "with priority stream dep zero", // golang.org/issue/15444
280 BlockFragment: []byte("abc"),
284 Priority: PriorityParam{
290 "\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x00\u007fabc\x00\x00",
292 FrameHeader: FrameHeader{
296 Flags: FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
297 Length: uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
299 Priority: PriorityParam{
304 headerFragBuf: []byte("abc"),
308 for _, tt := range tests {
309 fr, buf := testFramer()
310 if err := fr.WriteHeaders(tt.p); err != nil {
311 t.Errorf("test %q: %v", tt.name, err)
314 if buf.String() != tt.wantEnc {
315 t.Errorf("test %q: encoded %q; want %q", tt.name, buf.Bytes(), tt.wantEnc)
317 f, err := fr.ReadFrame()
319 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
322 if !reflect.DeepEqual(f, tt.wantFrame) {
323 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
328 func TestWriteInvalidStreamDep(t *testing.T) {
329 fr, _ := testFramer()
330 err := fr.WriteHeaders(HeadersFrameParam{
332 Priority: PriorityParam{
336 if err != errDepStreamID {
337 t.Errorf("header error = %v; want %q", err, errDepStreamID)
340 err = fr.WritePriority(2, PriorityParam{StreamDep: 1 << 31})
341 if err != errDepStreamID {
342 t.Errorf("priority error = %v; want %q", err, errDepStreamID)
346 func TestWriteContinuation(t *testing.T) {
353 wantFrame *ContinuationFrame
360 FrameHeader: FrameHeader{
363 Type: FrameContinuation,
364 Length: uint32(len("abc")),
366 headerFragBuf: []byte("abc"),
374 FrameHeader: FrameHeader{
377 Type: FrameContinuation,
378 Flags: FlagContinuationEndHeaders,
379 Length: uint32(len("def")),
381 headerFragBuf: []byte("def"),
385 for _, tt := range tests {
386 fr, _ := testFramer()
387 if err := fr.WriteContinuation(streamID, tt.end, tt.frag); err != nil {
388 t.Errorf("test %q: %v", tt.name, err)
391 fr.AllowIllegalReads = true
392 f, err := fr.ReadFrame()
394 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
397 if !reflect.DeepEqual(f, tt.wantFrame) {
398 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
403 func TestWritePriority(t *testing.T) {
407 priority PriorityParam
408 wantFrame *PriorityFrame
454 for _, tt := range tests {
455 fr, _ := testFramer()
456 if err := fr.WritePriority(streamID, tt.priority); err != nil {
457 t.Errorf("test %q: %v", tt.name, err)
460 f, err := fr.ReadFrame()
462 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
465 if !reflect.DeepEqual(f, tt.wantFrame) {
466 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
471 func TestWriteSettings(t *testing.T) {
472 fr, buf := testFramer()
473 settings := []Setting{{1, 2}, {3, 4}}
474 fr.WriteSettings(settings...)
475 const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
476 if buf.String() != wantEnc {
477 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
479 f, err := fr.ReadFrame()
483 sf, ok := f.(*SettingsFrame)
485 t.Fatalf("Got a %T; want a SettingsFrame", f)
488 sf.ForeachSetting(func(s Setting) error {
490 valBack, ok := sf.Value(s.ID)
491 if !ok || valBack != s.Val {
492 t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val)
496 if !reflect.DeepEqual(settings, got) {
497 t.Errorf("Read settings %+v != written settings %+v", got, settings)
501 func TestWriteSettingsAck(t *testing.T) {
502 fr, buf := testFramer()
503 fr.WriteSettingsAck()
504 const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
505 if buf.String() != wantEnc {
506 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
510 func TestWriteWindowUpdate(t *testing.T) {
511 fr, buf := testFramer()
512 const streamID = 1<<24 + 2<<16 + 3<<8 + 4
513 const incr = 7<<24 + 6<<16 + 5<<8 + 4
514 if err := fr.WriteWindowUpdate(streamID, incr); err != nil {
517 const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04"
518 if buf.String() != wantEnc {
519 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
521 f, err := fr.ReadFrame()
525 want := &WindowUpdateFrame{
526 FrameHeader: FrameHeader{
533 Increment: 0x7060504,
535 if !reflect.DeepEqual(f, want) {
536 t.Errorf("parsed back %#v; want %#v", f, want)
540 func TestWritePing(t *testing.T) { testWritePing(t, false) }
541 func TestWritePingAck(t *testing.T) { testWritePing(t, true) }
543 func testWritePing(t *testing.T, ack bool) {
544 fr, buf := testFramer()
545 if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil {
550 wantFlags = FlagPingAck
552 var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08"
553 if buf.String() != wantEnc {
554 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
557 f, err := fr.ReadFrame()
562 FrameHeader: FrameHeader{
569 Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
571 if !reflect.DeepEqual(f, want) {
572 t.Errorf("parsed back %#v; want %#v", f, want)
576 func TestReadFrameHeader(t *testing.T) {
581 {in: "\x00\x00\x00" + "\x00" + "\x00" + "\x00\x00\x00\x00", want: FrameHeader{}},
582 {in: "\x01\x02\x03" + "\x04" + "\x05" + "\x06\x07\x08\x09", want: FrameHeader{
583 Length: 66051, Type: 4, Flags: 5, StreamID: 101124105,
586 {in: "\xff\xff\xff" + "\xff" + "\xff" + "\xff\xff\xff\xff", want: FrameHeader{
587 Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
588 {in: "\xff\xff\xff" + "\xff" + "\xff" + "\x7f\xff\xff\xff", want: FrameHeader{
589 Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
591 for i, tt := range tests {
592 got, err := readFrameHeader(make([]byte, 9), strings.NewReader(tt.in))
594 t.Errorf("%d. readFrameHeader(%q) = %v", i, tt.in, err)
599 t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
604 func TestReadWriteFrameHeader(t *testing.T) {
611 {len: 0, typ: 255, flags: 1, streamID: 0},
612 {len: 0, typ: 255, flags: 1, streamID: 1},
613 {len: 0, typ: 255, flags: 1, streamID: 255},
614 {len: 0, typ: 255, flags: 1, streamID: 256},
615 {len: 0, typ: 255, flags: 1, streamID: 65535},
616 {len: 0, typ: 255, flags: 1, streamID: 65536},
618 {len: 0, typ: 1, flags: 255, streamID: 1},
619 {len: 255, typ: 1, flags: 255, streamID: 1},
620 {len: 256, typ: 1, flags: 255, streamID: 1},
621 {len: 65535, typ: 1, flags: 255, streamID: 1},
622 {len: 65536, typ: 1, flags: 255, streamID: 1},
623 {len: 16777215, typ: 1, flags: 255, streamID: 1},
625 for _, tt := range tests {
626 fr, buf := testFramer()
627 fr.startWrite(tt.typ, tt.flags, tt.streamID)
628 fr.writeBytes(make([]byte, tt.len))
630 fh, err := ReadFrameHeader(buf)
632 t.Errorf("ReadFrameHeader(%+v) = %v", tt, err)
635 if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID {
636 t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh)
642 func TestWriteTooLargeFrame(t *testing.T) {
643 fr, _ := testFramer()
644 fr.startWrite(0, 1, 1)
645 fr.writeBytes(make([]byte, 1<<24))
647 if err != ErrFrameTooLarge {
648 t.Errorf("endWrite = %v; want errFrameTooLarge", err)
652 func TestWriteGoAway(t *testing.T) {
654 fr, buf := testFramer()
655 if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil {
658 const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug
659 if buf.String() != wantEnc {
660 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
662 f, err := fr.ReadFrame()
666 want := &GoAwayFrame{
667 FrameHeader: FrameHeader{
671 Length: uint32(4 + 4 + len(debug)),
674 LastStreamID: 0x01020304,
676 debugData: []byte(debug),
678 if !reflect.DeepEqual(f, want) {
679 t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
681 if got := string(f.(*GoAwayFrame).DebugData()); got != debug {
682 t.Errorf("debug data = %q; want %q", got, debug)
686 func TestWritePushPromise(t *testing.T) {
687 pp := PushPromiseParam{
690 BlockFragment: []byte("abc"),
692 fr, buf := testFramer()
693 if err := fr.WritePushPromise(pp); err != nil {
696 const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc"
697 if buf.String() != wantEnc {
698 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
700 f, err := fr.ReadFrame()
704 _, ok := f.(*PushPromiseFrame)
706 t.Fatalf("got %T; want *PushPromiseFrame", f)
708 want := &PushPromiseFrame{
709 FrameHeader: FrameHeader{
717 headerFragBuf: []byte("abc"),
719 if !reflect.DeepEqual(f, want) {
720 t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
724 // test checkFrameOrder and that HEADERS and CONTINUATION frames can't be intermingled.
725 func TestReadFrameOrder(t *testing.T) {
726 head := func(f *Framer, id uint32, end bool) {
727 f.WriteHeaders(HeadersFrameParam{
729 BlockFragment: []byte("foo"), // unused, but non-empty
733 cont := func(f *Framer, id uint32, end bool) {
734 f.WriteContinuation(id, end, []byte("foo"))
737 tests := [...]struct {
755 wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1",
762 wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1",
775 wantErr: "got CONTINUATION for stream 2; expected stream 1",
783 wantErr: "unexpected CONTINUATION for stream 1",
789 wantErr: "unexpected CONTINUATION for stream 1",
795 wantErr: "HEADERS frame with stream ID 0",
801 wantErr: "CONTINUATION frame with stream ID 0",
807 wantErr: "unexpected CONTINUATION for stream 1",
819 for i, tt := range tests {
820 buf := new(bytes.Buffer)
821 f := NewFramer(buf, buf)
822 f.AllowIllegalWrites = true
824 f.WriteData(1, true, nil) // to test transition away from last step
831 got, err = f.ReadFrame()
832 fmt.Fprintf(&log, " read %v, %v\n", got, err)
841 ok := tt.wantErr == ""
842 if ok && err != nil {
843 t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes())
846 if !ok && err != ConnectionError(ErrCodeProtocol) {
847 t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes())
850 if !((f.errDetail == nil && tt.wantErr == "") || (fmt.Sprint(f.errDetail) == tt.wantErr)) {
851 t.Errorf("%d. framer eror = %q; want %q\n%s", i, f.errDetail, tt.wantErr, log.Bytes())
854 t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes())
859 func TestMetaFrameHeader(t *testing.T) {
860 write := func(f *Framer, frags ...[]byte) {
861 for i, frag := range frags {
862 end := (i == len(frags)-1)
864 f.WriteHeaders(HeadersFrameParam{
870 f.WriteContinuation(1, end, frag)
875 want := func(flags Flags, length uint32, pairs ...string) *MetaHeadersFrame {
876 mh := &MetaHeadersFrame{
877 HeadersFrame: &HeadersFrame{
878 FrameHeader: FrameHeader{
885 Fields: []hpack.HeaderField(nil),
888 mh.Fields = append(mh.Fields, hpack.HeaderField{
896 truncated := func(mh *MetaHeadersFrame) *MetaHeadersFrame {
901 const noFlags Flags = 0
903 oneKBString := strings.Repeat("a", 1<<10)
905 tests := [...]struct {
908 want interface{} // *MetaHeaderFrame or error
910 maxHeaderListSize uint32
913 name: "single_headers",
916 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/")
919 want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"),
922 name: "with_continuation",
925 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
926 write(f, all[:1], all[1:])
928 want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"),
931 name: "with_two_continuation",
934 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
935 write(f, all[:2], all[2:4], all[4:])
937 want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"),
940 name: "big_string_okay",
943 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
944 write(f, all[:2], all[2:])
946 want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString),
949 name: "big_string_error",
952 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
953 write(f, all[:2], all[2:])
955 maxHeaderListSize: (1 << 10) / 2,
956 want: ConnectionError(ErrCodeCompression),
959 name: "max_header_list_truncated",
962 var pairs = []string{":method", "GET", ":path", "/"}
963 for i := 0; i < 100; i++ {
964 pairs = append(pairs, "foo", "bar")
966 all := he.encodeHeaderRaw(t, pairs...)
967 write(f, all[:2], all[2:])
969 maxHeaderListSize: (1 << 10) / 2,
970 want: truncated(want(noFlags, 2,
987 name: "pseudo_order",
989 write(f, encodeHeaderRaw(t,
992 ":path", "/", // bogus
995 want: streamError(1, ErrCodeProtocol),
996 wantErrReason: "pseudo header field after regular",
999 name: "pseudo_unknown",
1000 w: func(f *Framer) {
1001 write(f, encodeHeaderRaw(t,
1002 ":unknown", "foo", // bogus
1006 want: streamError(1, ErrCodeProtocol),
1007 wantErrReason: "invalid pseudo-header \":unknown\"",
1010 name: "pseudo_mix_request_response",
1011 w: func(f *Framer) {
1012 write(f, encodeHeaderRaw(t,
1017 want: streamError(1, ErrCodeProtocol),
1018 wantErrReason: "mix of request and response pseudo headers",
1022 w: func(f *Framer) {
1023 write(f, encodeHeaderRaw(t,
1028 want: streamError(1, ErrCodeProtocol),
1029 wantErrReason: "duplicate pseudo-header \":method\"",
1032 name: "trailer_okay_no_pseudo",
1033 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) },
1034 want: want(FlagHeadersEndHeaders, 8, "foo", "bar"),
1037 name: "invalid_field_name",
1038 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) },
1039 want: streamError(1, ErrCodeProtocol),
1040 wantErrReason: "invalid header field name \"CapitalBad\"",
1043 name: "invalid_field_value",
1044 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) },
1045 want: streamError(1, ErrCodeProtocol),
1046 wantErrReason: "invalid header field value \"bad_null\\x00\"",
1049 for i, tt := range tests {
1050 buf := new(bytes.Buffer)
1051 f := NewFramer(buf, buf)
1052 f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
1053 f.MaxHeaderListSize = tt.maxHeaderListSize
1058 name = fmt.Sprintf("test index %d", i)
1063 got, err = f.ReadFrame()
1067 // Ignore the StreamError.Cause field, if it matches the wantErrReason.
1068 // The test table above predates the Cause field.
1069 if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason {
1074 if !reflect.DeepEqual(got, tt.want) {
1075 if mhg, ok := got.(*MetaHeadersFrame); ok {
1076 if mhw, ok := tt.want.(*MetaHeadersFrame); ok {
1077 hg := mhg.HeadersFrame
1078 hw := mhw.HeadersFrame
1079 if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) {
1080 t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw)
1084 str := func(v interface{}) string {
1085 if _, ok := v.(error); ok {
1086 return fmt.Sprintf("error %v", v)
1088 return fmt.Sprintf("value %#v", v)
1091 t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want))
1093 if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) {
1094 t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason)
1099 func TestSetReuseFrames(t *testing.T) {
1100 fr, buf := testFramer()
1103 // Check that DataFrames are reused. Note that
1104 // SetReuseFrames only currently implements reuse of DataFrames.
1105 firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1107 for i := 0; i < 10; i++ {
1108 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1110 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1114 for i := 0; i < 10; i++ {
1115 df := readAndVerifyDataFrame("", 0, fr, buf, t)
1117 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1121 for i := 0; i < 10; i++ {
1122 df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
1124 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1129 func TestSetReuseFramesMoreThanOnce(t *testing.T) {
1130 fr, buf := testFramer()
1133 firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1136 for i := 0; i < 10; i++ {
1137 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1138 // SetReuseFrames should be idempotent
1141 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1146 func TestNoSetReuseFrames(t *testing.T) {
1147 fr, buf := testFramer()
1148 const numNewDataFrames = 10
1149 dfSoFar := make([]interface{}, numNewDataFrames)
1151 // Check that DataFrames are not reused if SetReuseFrames wasn't called.
1152 // SetReuseFrames only currently implements reuse of DataFrames.
1153 for i := 0; i < numNewDataFrames; i++ {
1154 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1155 for _, item := range dfSoFar {
1157 t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
1164 func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
1165 var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
1166 fr.WriteData(streamID, true, []byte(data))
1167 wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
1168 if buf.String() != wantEnc {
1169 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
1171 f, err := fr.ReadFrame()
1175 df, ok := f.(*DataFrame)
1177 t.Fatalf("got %T; want *DataFrame", f)
1179 if !bytes.Equal(df.Data(), []byte(data)) {
1180 t.Errorf("got %q; want %q", df.Data(), []byte(data))
1182 if f.Header().Flags&1 == 0 {
1183 t.Errorf("didn't see END_STREAM flag")
1188 func encodeHeaderRaw(t *testing.T, pairs ...string) []byte {
1190 return he.encodeHeaderRaw(t, pairs...)