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
5package http2
6
7import (
8	"bytes"
9	"fmt"
10	"io"
11	"reflect"
12	"strings"
13	"testing"
14	"unsafe"
15
16	"golang.org/x/net/http2/hpack"
17)
18
19func testFramer() (*Framer, *bytes.Buffer) {
20	buf := new(bytes.Buffer)
21	return NewFramer(buf, buf), buf
22}
23
24func 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)
28	}
29}
30
31func TestFrameTypeString(t *testing.T) {
32	tests := []struct {
33		ft   FrameType
34		want string
35	}{
36		{FrameData, "DATA"},
37		{FramePing, "PING"},
38		{FrameGoAway, "GOAWAY"},
39		{0xf, "UNKNOWN_FRAME_TYPE_15"},
40	}
41
42	for i, tt := range tests {
43		got := tt.ft.String()
44		if got != tt.want {
45			t.Errorf("%d. String(FrameType %d) = %q; want %q", i, int(tt.ft), got, tt.want)
46		}
47	}
48}
49
50func 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)
58	}
59	f, err := fr.ReadFrame()
60	if err != nil {
61		t.Fatal(err)
62	}
63	want := &RSTStreamFrame{
64		FrameHeader: FrameHeader{
65			valid:    true,
66			Type:     0x3,
67			Flags:    0x0,
68			Length:   0x4,
69			StreamID: 0x1020304,
70		},
71		ErrCode: 0x7060504,
72	}
73	if !reflect.DeepEqual(f, want) {
74		t.Errorf("parsed back %#v; want %#v", f, want)
75	}
76}
77
78func TestWriteData(t *testing.T) {
79	fr, buf := testFramer()
80	var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
81	data := []byte("ABC")
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)
86	}
87	f, err := fr.ReadFrame()
88	if err != nil {
89		t.Fatal(err)
90	}
91	df, ok := f.(*DataFrame)
92	if !ok {
93		t.Fatalf("got %T; want *DataFrame", f)
94	}
95	if !bytes.Equal(df.Data(), data) {
96		t.Errorf("got %q; want %q", df.Data(), data)
97	}
98	if f.Header().Flags&1 == 0 {
99		t.Errorf("didn't see END_STREAM flag")
100	}
101}
102
103func TestWriteDataPadded(t *testing.T) {
104	tests := [...]struct {
105		streamID   uint32
106		endStream  bool
107		data       []byte
108		pad        []byte
109		wantHeader FrameHeader
110	}{
111		// Unpadded:
112		0: {
113			streamID:  1,
114			endStream: true,
115			data:      []byte("foo"),
116			pad:       nil,
117			wantHeader: FrameHeader{
118				Type:     FrameData,
119				Flags:    FlagDataEndStream,
120				Length:   3,
121				StreamID: 1,
122			},
123		},
124
125		// Padded bit set, but no padding:
126		1: {
127			streamID:  1,
128			endStream: true,
129			data:      []byte("foo"),
130			pad:       []byte{},
131			wantHeader: FrameHeader{
132				Type:     FrameData,
133				Flags:    FlagDataEndStream | FlagDataPadded,
134				Length:   4,
135				StreamID: 1,
136			},
137		},
138
139		// Padded bit set, with padding:
140		2: {
141			streamID:  1,
142			endStream: false,
143			data:      []byte("foo"),
144			pad:       []byte{0, 0, 0},
145			wantHeader: FrameHeader{
146				Type:     FrameData,
147				Flags:    FlagDataPadded,
148				Length:   7,
149				StreamID: 1,
150			},
151		},
152	}
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()
157		if err != nil {
158			t.Errorf("%d. ReadFrame: %v", i, err)
159			continue
160		}
161		got := f.Header()
162		tt.wantHeader.valid = true
163		if !got.Equal(tt.wantHeader) {
164			t.Errorf("%d. read %+v; want %+v", i, got, tt.wantHeader)
165			continue
166		}
167		df := f.(*DataFrame)
168		if !bytes.Equal(df.Data(), tt.data) {
169			t.Errorf("%d. got %q; want %q", i, df.Data(), tt.data)
170		}
171	}
172}
173
174func (fh FrameHeader) Equal(b FrameHeader) bool {
175	return fh.valid == b.valid &&
176		fh.Type == b.Type &&
177		fh.Flags == b.Flags &&
178		fh.Length == b.Length &&
179		fh.StreamID == b.StreamID
180}
181
182func TestWriteHeaders(t *testing.T) {
183	tests := []struct {
184		name      string
185		p         HeadersFrameParam
186		wantEnc   string
187		wantFrame *HeadersFrame
188	}{
189		{
190			"basic",
191			HeadersFrameParam{
192				StreamID:      42,
193				BlockFragment: []byte("abc"),
194				Priority:      PriorityParam{},
195			},
196			"\x00\x00\x03\x01\x00\x00\x00\x00*abc",
197			&HeadersFrame{
198				FrameHeader: FrameHeader{
199					valid:    true,
200					StreamID: 42,
201					Type:     FrameHeaders,
202					Length:   uint32(len("abc")),
203				},
204				Priority:      PriorityParam{},
205				headerFragBuf: []byte("abc"),
206			},
207		},
208		{
209			"basic + end flags",
210			HeadersFrameParam{
211				StreamID:      42,
212				BlockFragment: []byte("abc"),
213				EndStream:     true,
214				EndHeaders:    true,
215				Priority:      PriorityParam{},
216			},
217			"\x00\x00\x03\x01\x05\x00\x00\x00*abc",
218			&HeadersFrame{
219				FrameHeader: FrameHeader{
220					valid:    true,
221					StreamID: 42,
222					Type:     FrameHeaders,
223					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders,
224					Length:   uint32(len("abc")),
225				},
226				Priority:      PriorityParam{},
227				headerFragBuf: []byte("abc"),
228			},
229		},
230		{
231			"with padding",
232			HeadersFrameParam{
233				StreamID:      42,
234				BlockFragment: []byte("abc"),
235				EndStream:     true,
236				EndHeaders:    true,
237				PadLength:     5,
238				Priority:      PriorityParam{},
239			},
240			"\x00\x00\t\x01\r\x00\x00\x00*\x05abc\x00\x00\x00\x00\x00",
241			&HeadersFrame{
242				FrameHeader: FrameHeader{
243					valid:    true,
244					StreamID: 42,
245					Type:     FrameHeaders,
246					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded,
247					Length:   uint32(1 + len("abc") + 5), // pad length + contents + padding
248				},
249				Priority:      PriorityParam{},
250				headerFragBuf: []byte("abc"),
251			},
252		},
253		{
254			"with priority",
255			HeadersFrameParam{
256				StreamID:      42,
257				BlockFragment: []byte("abc"),
258				EndStream:     true,
259				EndHeaders:    true,
260				PadLength:     2,
261				Priority: PriorityParam{
262					StreamDep: 15,
263					Exclusive: true,
264					Weight:    127,
265				},
266			},
267			"\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x0f\u007fabc\x00\x00",
268			&HeadersFrame{
269				FrameHeader: FrameHeader{
270					valid:    true,
271					StreamID: 42,
272					Type:     FrameHeaders,
273					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
274					Length:   uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
275				},
276				Priority: PriorityParam{
277					StreamDep: 15,
278					Exclusive: true,
279					Weight:    127,
280				},
281				headerFragBuf: []byte("abc"),
282			},
283		},
284		{
285			"with priority stream dep zero", // golang.org/issue/15444
286			HeadersFrameParam{
287				StreamID:      42,
288				BlockFragment: []byte("abc"),
289				EndStream:     true,
290				EndHeaders:    true,
291				PadLength:     2,
292				Priority: PriorityParam{
293					StreamDep: 0,
294					Exclusive: true,
295					Weight:    127,
296				},
297			},
298			"\x00\x00\v\x01-\x00\x00\x00*\x02\x80\x00\x00\x00\u007fabc\x00\x00",
299			&HeadersFrame{
300				FrameHeader: FrameHeader{
301					valid:    true,
302					StreamID: 42,
303					Type:     FrameHeaders,
304					Flags:    FlagHeadersEndStream | FlagHeadersEndHeaders | FlagHeadersPadded | FlagHeadersPriority,
305					Length:   uint32(1 + 5 + len("abc") + 2), // pad length + priority + contents + padding
306				},
307				Priority: PriorityParam{
308					StreamDep: 0,
309					Exclusive: true,
310					Weight:    127,
311				},
312				headerFragBuf: []byte("abc"),
313			},
314		},
315	}
316	for _, tt := range tests {
317		fr, buf := testFramer()
318		if err := fr.WriteHeaders(tt.p); err != nil {
319			t.Errorf("test %q: %v", tt.name, err)
320			continue
321		}
322		if buf.String() != tt.wantEnc {
323			t.Errorf("test %q: encoded %q; want %q", tt.name, buf.Bytes(), tt.wantEnc)
324		}
325		f, err := fr.ReadFrame()
326		if err != nil {
327			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
328			continue
329		}
330		if !reflect.DeepEqual(f, tt.wantFrame) {
331			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
332		}
333	}
334}
335
336func TestWriteInvalidStreamDep(t *testing.T) {
337	fr, _ := testFramer()
338	err := fr.WriteHeaders(HeadersFrameParam{
339		StreamID: 42,
340		Priority: PriorityParam{
341			StreamDep: 1 << 31,
342		},
343	})
344	if err != errDepStreamID {
345		t.Errorf("header error = %v; want %q", err, errDepStreamID)
346	}
347
348	err = fr.WritePriority(2, PriorityParam{StreamDep: 1 << 31})
349	if err != errDepStreamID {
350		t.Errorf("priority error = %v; want %q", err, errDepStreamID)
351	}
352}
353
354func TestWriteContinuation(t *testing.T) {
355	const streamID = 42
356	tests := []struct {
357		name string
358		end  bool
359		frag []byte
360
361		wantFrame *ContinuationFrame
362	}{
363		{
364			"not end",
365			false,
366			[]byte("abc"),
367			&ContinuationFrame{
368				FrameHeader: FrameHeader{
369					valid:    true,
370					StreamID: streamID,
371					Type:     FrameContinuation,
372					Length:   uint32(len("abc")),
373				},
374				headerFragBuf: []byte("abc"),
375			},
376		},
377		{
378			"end",
379			true,
380			[]byte("def"),
381			&ContinuationFrame{
382				FrameHeader: FrameHeader{
383					valid:    true,
384					StreamID: streamID,
385					Type:     FrameContinuation,
386					Flags:    FlagContinuationEndHeaders,
387					Length:   uint32(len("def")),
388				},
389				headerFragBuf: []byte("def"),
390			},
391		},
392	}
393	for _, tt := range tests {
394		fr, _ := testFramer()
395		if err := fr.WriteContinuation(streamID, tt.end, tt.frag); err != nil {
396			t.Errorf("test %q: %v", tt.name, err)
397			continue
398		}
399		fr.AllowIllegalReads = true
400		f, err := fr.ReadFrame()
401		if err != nil {
402			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
403			continue
404		}
405		if !reflect.DeepEqual(f, tt.wantFrame) {
406			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
407		}
408	}
409}
410
411func TestWritePriority(t *testing.T) {
412	const streamID = 42
413	tests := []struct {
414		name      string
415		priority  PriorityParam
416		wantFrame *PriorityFrame
417	}{
418		{
419			"not exclusive",
420			PriorityParam{
421				StreamDep: 2,
422				Exclusive: false,
423				Weight:    127,
424			},
425			&PriorityFrame{
426				FrameHeader{
427					valid:    true,
428					StreamID: streamID,
429					Type:     FramePriority,
430					Length:   5,
431				},
432				PriorityParam{
433					StreamDep: 2,
434					Exclusive: false,
435					Weight:    127,
436				},
437			},
438		},
439
440		{
441			"exclusive",
442			PriorityParam{
443				StreamDep: 3,
444				Exclusive: true,
445				Weight:    77,
446			},
447			&PriorityFrame{
448				FrameHeader{
449					valid:    true,
450					StreamID: streamID,
451					Type:     FramePriority,
452					Length:   5,
453				},
454				PriorityParam{
455					StreamDep: 3,
456					Exclusive: true,
457					Weight:    77,
458				},
459			},
460		},
461	}
462	for _, tt := range tests {
463		fr, _ := testFramer()
464		if err := fr.WritePriority(streamID, tt.priority); err != nil {
465			t.Errorf("test %q: %v", tt.name, err)
466			continue
467		}
468		f, err := fr.ReadFrame()
469		if err != nil {
470			t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
471			continue
472		}
473		if !reflect.DeepEqual(f, tt.wantFrame) {
474			t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
475		}
476	}
477}
478
479func TestWriteSettings(t *testing.T) {
480	fr, buf := testFramer()
481	settings := []Setting{{1, 2}, {3, 4}}
482	fr.WriteSettings(settings...)
483	const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
484	if buf.String() != wantEnc {
485		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
486	}
487	f, err := fr.ReadFrame()
488	if err != nil {
489		t.Fatal(err)
490	}
491	sf, ok := f.(*SettingsFrame)
492	if !ok {
493		t.Fatalf("Got a %T; want a SettingsFrame", f)
494	}
495	var got []Setting
496	sf.ForeachSetting(func(s Setting) error {
497		got = append(got, s)
498		valBack, ok := sf.Value(s.ID)
499		if !ok || valBack != s.Val {
500			t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val)
501		}
502		return nil
503	})
504	if !reflect.DeepEqual(settings, got) {
505		t.Errorf("Read settings %+v != written settings %+v", got, settings)
506	}
507}
508
509func TestWriteSettingsAck(t *testing.T) {
510	fr, buf := testFramer()
511	fr.WriteSettingsAck()
512	const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
513	if buf.String() != wantEnc {
514		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
515	}
516}
517
518func TestWriteWindowUpdate(t *testing.T) {
519	fr, buf := testFramer()
520	const streamID = 1<<24 + 2<<16 + 3<<8 + 4
521	const incr = 7<<24 + 6<<16 + 5<<8 + 4
522	if err := fr.WriteWindowUpdate(streamID, incr); err != nil {
523		t.Fatal(err)
524	}
525	const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04"
526	if buf.String() != wantEnc {
527		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
528	}
529	f, err := fr.ReadFrame()
530	if err != nil {
531		t.Fatal(err)
532	}
533	want := &WindowUpdateFrame{
534		FrameHeader: FrameHeader{
535			valid:    true,
536			Type:     0x8,
537			Flags:    0x0,
538			Length:   0x4,
539			StreamID: 0x1020304,
540		},
541		Increment: 0x7060504,
542	}
543	if !reflect.DeepEqual(f, want) {
544		t.Errorf("parsed back %#v; want %#v", f, want)
545	}
546}
547
548func TestWritePing(t *testing.T)    { testWritePing(t, false) }
549func TestWritePingAck(t *testing.T) { testWritePing(t, true) }
550
551func testWritePing(t *testing.T, ack bool) {
552	fr, buf := testFramer()
553	if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil {
554		t.Fatal(err)
555	}
556	var wantFlags Flags
557	if ack {
558		wantFlags = FlagPingAck
559	}
560	var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08"
561	if buf.String() != wantEnc {
562		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
563	}
564
565	f, err := fr.ReadFrame()
566	if err != nil {
567		t.Fatal(err)
568	}
569	want := &PingFrame{
570		FrameHeader: FrameHeader{
571			valid:    true,
572			Type:     0x6,
573			Flags:    wantFlags,
574			Length:   0x8,
575			StreamID: 0,
576		},
577		Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
578	}
579	if !reflect.DeepEqual(f, want) {
580		t.Errorf("parsed back %#v; want %#v", f, want)
581	}
582}
583
584func TestReadFrameHeader(t *testing.T) {
585	tests := []struct {
586		in   string
587		want FrameHeader
588	}{
589		{in: "\x00\x00\x00" + "\x00" + "\x00" + "\x00\x00\x00\x00", want: FrameHeader{}},
590		{in: "\x01\x02\x03" + "\x04" + "\x05" + "\x06\x07\x08\x09", want: FrameHeader{
591			Length: 66051, Type: 4, Flags: 5, StreamID: 101124105,
592		}},
593		// Ignore high bit:
594		{in: "\xff\xff\xff" + "\xff" + "\xff" + "\xff\xff\xff\xff", want: FrameHeader{
595			Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
596		{in: "\xff\xff\xff" + "\xff" + "\xff" + "\x7f\xff\xff\xff", want: FrameHeader{
597			Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
598	}
599	for i, tt := range tests {
600		got, err := readFrameHeader(make([]byte, 9), strings.NewReader(tt.in))
601		if err != nil {
602			t.Errorf("%d. readFrameHeader(%q) = %v", i, tt.in, err)
603			continue
604		}
605		tt.want.valid = true
606		if !got.Equal(tt.want) {
607			t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
608		}
609	}
610}
611
612func TestReadWriteFrameHeader(t *testing.T) {
613	tests := []struct {
614		len      uint32
615		typ      FrameType
616		flags    Flags
617		streamID uint32
618	}{
619		{len: 0, typ: 255, flags: 1, streamID: 0},
620		{len: 0, typ: 255, flags: 1, streamID: 1},
621		{len: 0, typ: 255, flags: 1, streamID: 255},
622		{len: 0, typ: 255, flags: 1, streamID: 256},
623		{len: 0, typ: 255, flags: 1, streamID: 65535},
624		{len: 0, typ: 255, flags: 1, streamID: 65536},
625
626		{len: 0, typ: 1, flags: 255, streamID: 1},
627		{len: 255, typ: 1, flags: 255, streamID: 1},
628		{len: 256, typ: 1, flags: 255, streamID: 1},
629		{len: 65535, typ: 1, flags: 255, streamID: 1},
630		{len: 65536, typ: 1, flags: 255, streamID: 1},
631		{len: 16777215, typ: 1, flags: 255, streamID: 1},
632	}
633	for _, tt := range tests {
634		fr, buf := testFramer()
635		fr.startWrite(tt.typ, tt.flags, tt.streamID)
636		fr.writeBytes(make([]byte, tt.len))
637		fr.endWrite()
638		fh, err := ReadFrameHeader(buf)
639		if err != nil {
640			t.Errorf("ReadFrameHeader(%+v) = %v", tt, err)
641			continue
642		}
643		if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID {
644			t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh)
645		}
646	}
647
648}
649
650func TestWriteTooLargeFrame(t *testing.T) {
651	fr, _ := testFramer()
652	fr.startWrite(0, 1, 1)
653	fr.writeBytes(make([]byte, 1<<24))
654	err := fr.endWrite()
655	if err != ErrFrameTooLarge {
656		t.Errorf("endWrite = %v; want errFrameTooLarge", err)
657	}
658}
659
660func TestWriteGoAway(t *testing.T) {
661	const debug = "foo"
662	fr, buf := testFramer()
663	if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil {
664		t.Fatal(err)
665	}
666	const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug
667	if buf.String() != wantEnc {
668		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
669	}
670	f, err := fr.ReadFrame()
671	if err != nil {
672		t.Fatal(err)
673	}
674	want := &GoAwayFrame{
675		FrameHeader: FrameHeader{
676			valid:    true,
677			Type:     0x7,
678			Flags:    0,
679			Length:   uint32(4 + 4 + len(debug)),
680			StreamID: 0,
681		},
682		LastStreamID: 0x01020304,
683		ErrCode:      0x05060708,
684		debugData:    []byte(debug),
685	}
686	if !reflect.DeepEqual(f, want) {
687		t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
688	}
689	if got := string(f.(*GoAwayFrame).DebugData()); got != debug {
690		t.Errorf("debug data = %q; want %q", got, debug)
691	}
692}
693
694func TestWritePushPromise(t *testing.T) {
695	pp := PushPromiseParam{
696		StreamID:      42,
697		PromiseID:     42,
698		BlockFragment: []byte("abc"),
699	}
700	fr, buf := testFramer()
701	if err := fr.WritePushPromise(pp); err != nil {
702		t.Fatal(err)
703	}
704	const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc"
705	if buf.String() != wantEnc {
706		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
707	}
708	f, err := fr.ReadFrame()
709	if err != nil {
710		t.Fatal(err)
711	}
712	_, ok := f.(*PushPromiseFrame)
713	if !ok {
714		t.Fatalf("got %T; want *PushPromiseFrame", f)
715	}
716	want := &PushPromiseFrame{
717		FrameHeader: FrameHeader{
718			valid:    true,
719			Type:     0x5,
720			Flags:    0x0,
721			Length:   0x7,
722			StreamID: 42,
723		},
724		PromiseID:     42,
725		headerFragBuf: []byte("abc"),
726	}
727	if !reflect.DeepEqual(f, want) {
728		t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
729	}
730}
731
732// test checkFrameOrder and that HEADERS and CONTINUATION frames can't be intermingled.
733func TestReadFrameOrder(t *testing.T) {
734	head := func(f *Framer, id uint32, end bool) {
735		f.WriteHeaders(HeadersFrameParam{
736			StreamID:      id,
737			BlockFragment: []byte("foo"), // unused, but non-empty
738			EndHeaders:    end,
739		})
740	}
741	cont := func(f *Framer, id uint32, end bool) {
742		f.WriteContinuation(id, end, []byte("foo"))
743	}
744
745	tests := [...]struct {
746		name    string
747		w       func(*Framer)
748		atLeast int
749		wantErr string
750	}{
751		0: {
752			w: func(f *Framer) {
753				head(f, 1, true)
754			},
755		},
756		1: {
757			w: func(f *Framer) {
758				head(f, 1, true)
759				head(f, 2, true)
760			},
761		},
762		2: {
763			wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1",
764			w: func(f *Framer) {
765				head(f, 1, false)
766				head(f, 2, true)
767			},
768		},
769		3: {
770			wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1",
771			w: func(f *Framer) {
772				head(f, 1, false)
773			},
774		},
775		4: {
776			w: func(f *Framer) {
777				head(f, 1, false)
778				cont(f, 1, true)
779				head(f, 2, true)
780			},
781		},
782		5: {
783			wantErr: "got CONTINUATION for stream 2; expected stream 1",
784			w: func(f *Framer) {
785				head(f, 1, false)
786				cont(f, 2, true)
787				head(f, 2, true)
788			},
789		},
790		6: {
791			wantErr: "unexpected CONTINUATION for stream 1",
792			w: func(f *Framer) {
793				cont(f, 1, true)
794			},
795		},
796		7: {
797			wantErr: "unexpected CONTINUATION for stream 1",
798			w: func(f *Framer) {
799				cont(f, 1, false)
800			},
801		},
802		8: {
803			wantErr: "HEADERS frame with stream ID 0",
804			w: func(f *Framer) {
805				head(f, 0, true)
806			},
807		},
808		9: {
809			wantErr: "CONTINUATION frame with stream ID 0",
810			w: func(f *Framer) {
811				cont(f, 0, true)
812			},
813		},
814		10: {
815			wantErr: "unexpected CONTINUATION for stream 1",
816			atLeast: 5,
817			w: func(f *Framer) {
818				head(f, 1, false)
819				cont(f, 1, false)
820				cont(f, 1, false)
821				cont(f, 1, false)
822				cont(f, 1, true)
823				cont(f, 1, false)
824			},
825		},
826	}
827	for i, tt := range tests {
828		buf := new(bytes.Buffer)
829		f := NewFramer(buf, buf)
830		f.AllowIllegalWrites = true
831		tt.w(f)
832		f.WriteData(1, true, nil) // to test transition away from last step
833
834		var err error
835		n := 0
836		var log bytes.Buffer
837		for {
838			var got Frame
839			got, err = f.ReadFrame()
840			fmt.Fprintf(&log, "  read %v, %v\n", got, err)
841			if err != nil {
842				break
843			}
844			n++
845		}
846		if err == io.EOF {
847			err = nil
848		}
849		ok := tt.wantErr == ""
850		if ok && err != nil {
851			t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes())
852			continue
853		}
854		if !ok && err != ConnectionError(ErrCodeProtocol) {
855			t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes())
856			continue
857		}
858		if !((f.errDetail == nil && tt.wantErr == "") || (fmt.Sprint(f.errDetail) == tt.wantErr)) {
859			t.Errorf("%d. framer eror = %q; want %q\n%s", i, f.errDetail, tt.wantErr, log.Bytes())
860		}
861		if n < tt.atLeast {
862			t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes())
863		}
864	}
865}
866
867func TestMetaFrameHeader(t *testing.T) {
868	write := func(f *Framer, frags ...[]byte) {
869		for i, frag := range frags {
870			end := (i == len(frags)-1)
871			if i == 0 {
872				f.WriteHeaders(HeadersFrameParam{
873					StreamID:      1,
874					BlockFragment: frag,
875					EndHeaders:    end,
876				})
877			} else {
878				f.WriteContinuation(1, end, frag)
879			}
880		}
881	}
882
883	want := func(flags Flags, length uint32, pairs ...string) *MetaHeadersFrame {
884		mh := &MetaHeadersFrame{
885			HeadersFrame: &HeadersFrame{
886				FrameHeader: FrameHeader{
887					Type:     FrameHeaders,
888					Flags:    flags,
889					Length:   length,
890					StreamID: 1,
891				},
892			},
893			Fields: []hpack.HeaderField(nil),
894		}
895		for len(pairs) > 0 {
896			mh.Fields = append(mh.Fields, hpack.HeaderField{
897				Name:  pairs[0],
898				Value: pairs[1],
899			})
900			pairs = pairs[2:]
901		}
902		return mh
903	}
904	truncated := func(mh *MetaHeadersFrame) *MetaHeadersFrame {
905		mh.Truncated = true
906		return mh
907	}
908
909	const noFlags Flags = 0
910
911	oneKBString := strings.Repeat("a", 1<<10)
912
913	tests := [...]struct {
914		name              string
915		w                 func(*Framer)
916		want              interface{} // *MetaHeaderFrame or error
917		wantErrReason     string
918		maxHeaderListSize uint32
919	}{
920		0: {
921			name: "single_headers",
922			w: func(f *Framer) {
923				var he hpackEncoder
924				all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/")
925				write(f, all)
926			},
927			want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"),
928		},
929		1: {
930			name: "with_continuation",
931			w: func(f *Framer) {
932				var he hpackEncoder
933				all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
934				write(f, all[:1], all[1:])
935			},
936			want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"),
937		},
938		2: {
939			name: "with_two_continuation",
940			w: func(f *Framer) {
941				var he hpackEncoder
942				all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
943				write(f, all[:2], all[2:4], all[4:])
944			},
945			want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"),
946		},
947		3: {
948			name: "big_string_okay",
949			w: func(f *Framer) {
950				var he hpackEncoder
951				all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
952				write(f, all[:2], all[2:])
953			},
954			want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString),
955		},
956		4: {
957			name: "big_string_error",
958			w: func(f *Framer) {
959				var he hpackEncoder
960				all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
961				write(f, all[:2], all[2:])
962			},
963			maxHeaderListSize: (1 << 10) / 2,
964			want:              ConnectionError(ErrCodeCompression),
965		},
966		5: {
967			name: "max_header_list_truncated",
968			w: func(f *Framer) {
969				var he hpackEncoder
970				var pairs = []string{":method", "GET", ":path", "/"}
971				for i := 0; i < 100; i++ {
972					pairs = append(pairs, "foo", "bar")
973				}
974				all := he.encodeHeaderRaw(t, pairs...)
975				write(f, all[:2], all[2:])
976			},
977			maxHeaderListSize: (1 << 10) / 2,
978			want: truncated(want(noFlags, 2,
979				":method", "GET",
980				":path", "/",
981				"foo", "bar",
982				"foo", "bar",
983				"foo", "bar",
984				"foo", "bar",
985				"foo", "bar",
986				"foo", "bar",
987				"foo", "bar",
988				"foo", "bar",
989				"foo", "bar",
990				"foo", "bar",
991				"foo", "bar", // 11
992			)),
993		},
994		6: {
995			name: "pseudo_order",
996			w: func(f *Framer) {
997				write(f, encodeHeaderRaw(t,
998					":method", "GET",
999					"foo", "bar",
1000					":path", "/", // bogus
1001				))
1002			},
1003			want:          streamError(1, ErrCodeProtocol),
1004			wantErrReason: "pseudo header field after regular",
1005		},
1006		7: {
1007			name: "pseudo_unknown",
1008			w: func(f *Framer) {
1009				write(f, encodeHeaderRaw(t,
1010					":unknown", "foo", // bogus
1011					"foo", "bar",
1012				))
1013			},
1014			want:          streamError(1, ErrCodeProtocol),
1015			wantErrReason: "invalid pseudo-header \":unknown\"",
1016		},
1017		8: {
1018			name: "pseudo_mix_request_response",
1019			w: func(f *Framer) {
1020				write(f, encodeHeaderRaw(t,
1021					":method", "GET",
1022					":status", "100",
1023				))
1024			},
1025			want:          streamError(1, ErrCodeProtocol),
1026			wantErrReason: "mix of request and response pseudo headers",
1027		},
1028		9: {
1029			name: "pseudo_dup",
1030			w: func(f *Framer) {
1031				write(f, encodeHeaderRaw(t,
1032					":method", "GET",
1033					":method", "POST",
1034				))
1035			},
1036			want:          streamError(1, ErrCodeProtocol),
1037			wantErrReason: "duplicate pseudo-header \":method\"",
1038		},
1039		10: {
1040			name: "trailer_okay_no_pseudo",
1041			w:    func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) },
1042			want: want(FlagHeadersEndHeaders, 8, "foo", "bar"),
1043		},
1044		11: {
1045			name:          "invalid_field_name",
1046			w:             func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) },
1047			want:          streamError(1, ErrCodeProtocol),
1048			wantErrReason: "invalid header field name \"CapitalBad\"",
1049		},
1050		12: {
1051			name:          "invalid_field_value",
1052			w:             func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) },
1053			want:          streamError(1, ErrCodeProtocol),
1054			wantErrReason: "invalid header field value \"bad_null\\x00\"",
1055		},
1056	}
1057	for i, tt := range tests {
1058		buf := new(bytes.Buffer)
1059		f := NewFramer(buf, buf)
1060		f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
1061		f.MaxHeaderListSize = tt.maxHeaderListSize
1062		tt.w(f)
1063
1064		name := tt.name
1065		if name == "" {
1066			name = fmt.Sprintf("test index %d", i)
1067		}
1068
1069		var got interface{}
1070		var err error
1071		got, err = f.ReadFrame()
1072		if err != nil {
1073			got = err
1074
1075			// Ignore the StreamError.Cause field, if it matches the wantErrReason.
1076			// The test table above predates the Cause field.
1077			if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason {
1078				se.Cause = nil
1079				got = se
1080			}
1081		}
1082		if !reflect.DeepEqual(got, tt.want) {
1083			if mhg, ok := got.(*MetaHeadersFrame); ok {
1084				if mhw, ok := tt.want.(*MetaHeadersFrame); ok {
1085					hg := mhg.HeadersFrame
1086					hw := mhw.HeadersFrame
1087					if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) {
1088						t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw)
1089					}
1090				}
1091			}
1092			str := func(v interface{}) string {
1093				if _, ok := v.(error); ok {
1094					return fmt.Sprintf("error %v", v)
1095				} else {
1096					return fmt.Sprintf("value %#v", v)
1097				}
1098			}
1099			t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want))
1100		}
1101		if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) {
1102			t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason)
1103		}
1104	}
1105}
1106
1107func TestSetReuseFrames(t *testing.T) {
1108	fr, buf := testFramer()
1109	fr.SetReuseFrames()
1110
1111	// Check that DataFrames are reused. Note that
1112	// SetReuseFrames only currently implements reuse of DataFrames.
1113	firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1114
1115	for i := 0; i < 10; i++ {
1116		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1117		if df != firstDf {
1118			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1119		}
1120	}
1121
1122	for i := 0; i < 10; i++ {
1123		df := readAndVerifyDataFrame("", 0, fr, buf, t)
1124		if df != firstDf {
1125			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1126		}
1127	}
1128
1129	for i := 0; i < 10; i++ {
1130		df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
1131		if df != firstDf {
1132			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1133		}
1134	}
1135}
1136
1137func TestSetReuseFramesMoreThanOnce(t *testing.T) {
1138	fr, buf := testFramer()
1139	fr.SetReuseFrames()
1140
1141	firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1142	fr.SetReuseFrames()
1143
1144	for i := 0; i < 10; i++ {
1145		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1146		// SetReuseFrames should be idempotent
1147		fr.SetReuseFrames()
1148		if df != firstDf {
1149			t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1150		}
1151	}
1152}
1153
1154func TestNoSetReuseFrames(t *testing.T) {
1155	fr, buf := testFramer()
1156	const numNewDataFrames = 10
1157	dfSoFar := make([]interface{}, numNewDataFrames)
1158
1159	// Check that DataFrames are not reused if SetReuseFrames wasn't called.
1160	// SetReuseFrames only currently implements reuse of DataFrames.
1161	for i := 0; i < numNewDataFrames; i++ {
1162		df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1163		for _, item := range dfSoFar {
1164			if df == item {
1165				t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
1166			}
1167		}
1168		dfSoFar[i] = df
1169	}
1170}
1171
1172func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
1173	var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
1174	fr.WriteData(streamID, true, []byte(data))
1175	wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
1176	if buf.String() != wantEnc {
1177		t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
1178	}
1179	f, err := fr.ReadFrame()
1180	if err != nil {
1181		t.Fatal(err)
1182	}
1183	df, ok := f.(*DataFrame)
1184	if !ok {
1185		t.Fatalf("got %T; want *DataFrame", f)
1186	}
1187	if !bytes.Equal(df.Data(), []byte(data)) {
1188		t.Errorf("got %q; want %q", df.Data(), []byte(data))
1189	}
1190	if f.Header().Flags&1 == 0 {
1191		t.Errorf("didn't see END_STREAM flag")
1192	}
1193	return df
1194}
1195
1196func encodeHeaderRaw(t *testing.T, pairs ...string) []byte {
1197	var he hpackEncoder
1198	return he.encodeHeaderRaw(t, pairs...)
1199}
1200
1201func TestSettingsDuplicates(t *testing.T) {
1202	tests := []struct {
1203		settings []Setting
1204		want     bool
1205	}{
1206		{nil, false},
1207		{[]Setting{{ID: 1}}, false},
1208		{[]Setting{{ID: 1}, {ID: 2}}, false},
1209		{[]Setting{{ID: 1}, {ID: 2}}, false},
1210		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
1211		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
1212		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}}, false},
1213
1214		{[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 2}}, true},
1215		{[]Setting{{ID: 4}, {ID: 2}, {ID: 3}, {ID: 4}}, true},
1216
1217		{[]Setting{
1218			{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
1219			{ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
1220			{ID: 9}, {ID: 10}, {ID: 11}, {ID: 12},
1221		}, false},
1222
1223		{[]Setting{
1224			{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
1225			{ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
1226			{ID: 9}, {ID: 10}, {ID: 11}, {ID: 11},
1227		}, true},
1228	}
1229	for i, tt := range tests {
1230		fr, _ := testFramer()
1231		fr.WriteSettings(tt.settings...)
1232		f, err := fr.ReadFrame()
1233		if err != nil {
1234			t.Fatalf("%d. ReadFrame: %v", i, err)
1235		}
1236		sf := f.(*SettingsFrame)
1237		got := sf.HasDuplicates()
1238		if got != tt.want {
1239			t.Errorf("%d. HasDuplicates = %v; want %v", i, got, tt.want)
1240		}
1241	}
1242
1243}
1244