1
2
3
4
5 package http2
6
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "reflect"
12 "strings"
13 "testing"
14 "unsafe"
15
16 "golang.org/x/net/http2/hpack"
17 )
18
19 func testFramer() (*Framer, *bytes.Buffer) {
20 buf := new(bytes.Buffer)
21 return NewFramer(buf, buf), buf
22 }
23
24 func TestFrameSizes(t *testing.T) {
25
26 if got, want := int(unsafe.Sizeof(FrameHeader{})), 12; got != want {
27 t.Errorf("FrameHeader size = %d; want %d", got, want)
28 }
29 }
30
31 func TestFrameTypeString(t *testing.T) {
32 tests := []struct {
33 ft FrameType
34 want string
35 }{
36 {FrameData, "DATA"},
37 {FramePing, "PING"},
38 {FrameGoAway, "GOAWAY"},
39 {0x20, "UNKNOWN_FRAME_TYPE_32"},
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
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)
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
78 func 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
103 func TestWriteDataPadded(t *testing.T) {
104 tests := [...]struct {
105 streamID uint32
106 endStream bool
107 data []byte
108 pad []byte
109 wantHeader FrameHeader
110 }{
111
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
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
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
174 func (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
182 func 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),
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),
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",
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),
306 },
307 Priority: PriorityParam{
308 StreamDep: 0,
309 Exclusive: true,
310 Weight: 127,
311 },
312 headerFragBuf: []byte("abc"),
313 },
314 },
315 {
316 "zero length",
317 HeadersFrameParam{
318 StreamID: 42,
319 Priority: PriorityParam{},
320 },
321 "\x00\x00\x00\x01\x00\x00\x00\x00*",
322 &HeadersFrame{
323 FrameHeader: FrameHeader{
324 valid: true,
325 StreamID: 42,
326 Type: FrameHeaders,
327 Length: 0,
328 },
329 Priority: PriorityParam{},
330 },
331 },
332 }
333 for _, tt := range tests {
334 fr, buf := testFramer()
335 if err := fr.WriteHeaders(tt.p); err != nil {
336 t.Errorf("test %q: %v", tt.name, err)
337 continue
338 }
339 if buf.String() != tt.wantEnc {
340 t.Errorf("test %q: encoded %q; want %q", tt.name, buf.Bytes(), tt.wantEnc)
341 }
342 f, err := fr.ReadFrame()
343 if err != nil {
344 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
345 continue
346 }
347 if !reflect.DeepEqual(f, tt.wantFrame) {
348 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
349 }
350 }
351 }
352
353 func TestWriteInvalidStreamDep(t *testing.T) {
354 fr, _ := testFramer()
355 err := fr.WriteHeaders(HeadersFrameParam{
356 StreamID: 42,
357 Priority: PriorityParam{
358 StreamDep: 1 << 31,
359 },
360 })
361 if err != errDepStreamID {
362 t.Errorf("header error = %v; want %q", err, errDepStreamID)
363 }
364
365 err = fr.WritePriority(2, PriorityParam{StreamDep: 1 << 31})
366 if err != errDepStreamID {
367 t.Errorf("priority error = %v; want %q", err, errDepStreamID)
368 }
369 }
370
371 func TestWriteContinuation(t *testing.T) {
372 const streamID = 42
373 tests := []struct {
374 name string
375 end bool
376 frag []byte
377
378 wantFrame *ContinuationFrame
379 }{
380 {
381 "not end",
382 false,
383 []byte("abc"),
384 &ContinuationFrame{
385 FrameHeader: FrameHeader{
386 valid: true,
387 StreamID: streamID,
388 Type: FrameContinuation,
389 Length: uint32(len("abc")),
390 },
391 headerFragBuf: []byte("abc"),
392 },
393 },
394 {
395 "end",
396 true,
397 []byte("def"),
398 &ContinuationFrame{
399 FrameHeader: FrameHeader{
400 valid: true,
401 StreamID: streamID,
402 Type: FrameContinuation,
403 Flags: FlagContinuationEndHeaders,
404 Length: uint32(len("def")),
405 },
406 headerFragBuf: []byte("def"),
407 },
408 },
409 }
410 for _, tt := range tests {
411 fr, _ := testFramer()
412 if err := fr.WriteContinuation(streamID, tt.end, tt.frag); err != nil {
413 t.Errorf("test %q: %v", tt.name, err)
414 continue
415 }
416 fr.AllowIllegalReads = true
417 f, err := fr.ReadFrame()
418 if err != nil {
419 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
420 continue
421 }
422 if !reflect.DeepEqual(f, tt.wantFrame) {
423 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
424 }
425 }
426 }
427
428 func TestParseRFC9218Priority(t *testing.T) {
429 tests := []struct {
430 name string
431 priorityStr string
432 want PriorityParam
433 wantOk bool
434 }{
435 {
436 name: "with urgency",
437 priorityStr: "u=0",
438 want: PriorityParam{
439 urgency: 0,
440 incremental: 0,
441 },
442 wantOk: true,
443 },
444 {
445 name: "with implicit incremental",
446 priorityStr: "i",
447 want: PriorityParam{
448 urgency: 3,
449 incremental: 1,
450 },
451 wantOk: true,
452 },
453 {
454 name: "with explicit incremental",
455 priorityStr: "i=?1",
456 want: PriorityParam{
457 urgency: 3,
458 incremental: 1,
459 },
460 wantOk: true,
461 },
462 {
463 name: "with urgency and incremental",
464 priorityStr: "i=?0, u=4",
465 want: PriorityParam{
466 urgency: 4,
467 incremental: 0,
468 },
469 wantOk: true,
470 },
471 {
472 name: "with other valid dictionary data",
473 priorityStr: "some=data;someparam;u=fake, u=1;foo, i;bar",
474 want: PriorityParam{
475 urgency: 1,
476 incremental: 1,
477 },
478 wantOk: true,
479 },
480 {
481 name: "repeated field",
482 priorityStr: "u=1,i,u=5,i=?0",
483 want: PriorityParam{
484 urgency: 5,
485 incremental: 0,
486 },
487 wantOk: true,
488 },
489 {
490 name: "wrong field type",
491 priorityStr: `u="urgency will be ignored", i`,
492 want: PriorityParam{
493 urgency: 3,
494 incremental: 1,
495 },
496 wantOk: true,
497 },
498 {
499 name: "invalid dictionary",
500 priorityStr: `u=1,i, but this is not a valid dictionary"`,
501 want: defaultRFC9218Priority(true),
502 },
503 {
504 name: "out of range value",
505 priorityStr: "u=8",
506 want: defaultRFC9218Priority(true),
507 wantOk: true,
508 },
509 }
510 for _, tt := range tests {
511 got, gotOk := parseRFC9218Priority(tt.priorityStr, true)
512 if gotOk != tt.wantOk {
513 t.Errorf("test %q: mismatch.\n got ok: %#v\nwant ok: %#v\n", tt.name, got, tt.want)
514 }
515 if got != tt.want {
516 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, got, tt.want)
517 }
518 }
519 }
520
521 func TestWritePriority(t *testing.T) {
522 const streamID = 42
523 tests := []struct {
524 name string
525 priority PriorityParam
526 wantFrame *PriorityFrame
527 }{
528 {
529 "not exclusive",
530 PriorityParam{
531 StreamDep: 2,
532 Exclusive: false,
533 Weight: 127,
534 },
535 &PriorityFrame{
536 FrameHeader{
537 valid: true,
538 StreamID: streamID,
539 Type: FramePriority,
540 Length: 5,
541 },
542 PriorityParam{
543 StreamDep: 2,
544 Exclusive: false,
545 Weight: 127,
546 },
547 },
548 },
549
550 {
551 "exclusive",
552 PriorityParam{
553 StreamDep: 3,
554 Exclusive: true,
555 Weight: 77,
556 },
557 &PriorityFrame{
558 FrameHeader{
559 valid: true,
560 StreamID: streamID,
561 Type: FramePriority,
562 Length: 5,
563 },
564 PriorityParam{
565 StreamDep: 3,
566 Exclusive: true,
567 Weight: 77,
568 },
569 },
570 },
571 }
572 for _, tt := range tests {
573 fr, _ := testFramer()
574 if err := fr.WritePriority(streamID, tt.priority); err != nil {
575 t.Errorf("test %q: %v", tt.name, err)
576 continue
577 }
578 f, err := fr.ReadFrame()
579 if err != nil {
580 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
581 continue
582 }
583 if !reflect.DeepEqual(f, tt.wantFrame) {
584 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
585 }
586 }
587 }
588
589 func TestWritePriorityUpdate(t *testing.T) {
590 const streamID = 42
591 tests := []struct {
592 name string
593 priority string
594 wantFrame *PriorityUpdateFrame
595 }{
596 {
597 name: "with urgency",
598 priority: "u=0",
599 wantFrame: &PriorityUpdateFrame{
600 FrameHeader: FrameHeader{
601 valid: true,
602 StreamID: 0,
603 Type: FramePriorityUpdate,
604 Length: 7,
605 },
606 Priority: "u=0",
607 PrioritizedStreamID: streamID,
608 },
609 },
610 {
611 name: "with incremental",
612 priority: "i",
613 wantFrame: &PriorityUpdateFrame{
614 FrameHeader: FrameHeader{
615 valid: true,
616 StreamID: 0,
617 Type: FramePriorityUpdate,
618 Length: 5,
619 },
620 Priority: "i",
621 PrioritizedStreamID: streamID,
622 },
623 },
624 {
625 name: "with urgency and incremental",
626 priority: "u=7,i",
627 wantFrame: &PriorityUpdateFrame{
628 FrameHeader: FrameHeader{
629 valid: true,
630 StreamID: 0,
631 Type: FramePriorityUpdate,
632 Length: 9,
633 },
634 Priority: "u=7,i",
635 PrioritizedStreamID: streamID,
636 },
637 },
638 {
639 name: "with other fields",
640 priority: "a=123,u=7,i,b;a;b",
641 wantFrame: &PriorityUpdateFrame{
642 FrameHeader: FrameHeader{
643 valid: true,
644 StreamID: 0,
645 Type: FramePriorityUpdate,
646 Length: 21,
647 },
648 Priority: "a=123,u=7,i,b;a;b",
649 PrioritizedStreamID: streamID,
650 },
651 },
652 {
653 name: "with string escapes",
654 priority: "u=\"invalid\" , i",
655 wantFrame: &PriorityUpdateFrame{
656 FrameHeader: FrameHeader{
657 valid: true,
658 StreamID: 0,
659 Type: FramePriorityUpdate,
660 Length: 19,
661 },
662 Priority: "u=\"invalid\" , i",
663 PrioritizedStreamID: streamID,
664 },
665 },
666 {
667 name: "with empty payload",
668 priority: "",
669 wantFrame: &PriorityUpdateFrame{
670 FrameHeader: FrameHeader{
671 valid: true,
672 StreamID: 0,
673 Type: FramePriorityUpdate,
674 Length: 4,
675 },
676 Priority: "",
677 PrioritizedStreamID: streamID,
678 },
679 },
680 }
681 for _, tt := range tests {
682 fr, _ := testFramer()
683 if err := fr.WritePriorityUpdate(streamID, tt.priority); err != nil {
684 t.Errorf("test %q: %v", tt.name, err)
685 continue
686 }
687 f, err := fr.ReadFrame()
688 if err != nil {
689 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
690 continue
691 }
692 if !reflect.DeepEqual(f, tt.wantFrame) {
693 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
694 }
695 }
696 }
697
698 func TestWriteSettings(t *testing.T) {
699 fr, buf := testFramer()
700 settings := []Setting{{1, 2}, {3, 4}}
701 fr.WriteSettings(settings...)
702 const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
703 if buf.String() != wantEnc {
704 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
705 }
706 f, err := fr.ReadFrame()
707 if err != nil {
708 t.Fatal(err)
709 }
710 sf, ok := f.(*SettingsFrame)
711 if !ok {
712 t.Fatalf("Got a %T; want a SettingsFrame", f)
713 }
714 var got []Setting
715 sf.ForeachSetting(func(s Setting) error {
716 got = append(got, s)
717 valBack, ok := sf.Value(s.ID)
718 if !ok || valBack != s.Val {
719 t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val)
720 }
721 return nil
722 })
723 if !reflect.DeepEqual(settings, got) {
724 t.Errorf("Read settings %+v != written settings %+v", got, settings)
725 }
726 }
727
728 func TestWriteSettingsAck(t *testing.T) {
729 fr, buf := testFramer()
730 fr.WriteSettingsAck()
731 const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
732 if buf.String() != wantEnc {
733 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
734 }
735 }
736
737 func TestWriteWindowUpdate(t *testing.T) {
738 fr, buf := testFramer()
739 const streamID = 1<<24 + 2<<16 + 3<<8 + 4
740 const incr = 7<<24 + 6<<16 + 5<<8 + 4
741 if err := fr.WriteWindowUpdate(streamID, incr); err != nil {
742 t.Fatal(err)
743 }
744 const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04"
745 if buf.String() != wantEnc {
746 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
747 }
748 f, err := fr.ReadFrame()
749 if err != nil {
750 t.Fatal(err)
751 }
752 want := &WindowUpdateFrame{
753 FrameHeader: FrameHeader{
754 valid: true,
755 Type: 0x8,
756 Flags: 0x0,
757 Length: 0x4,
758 StreamID: 0x1020304,
759 },
760 Increment: 0x7060504,
761 }
762 if !reflect.DeepEqual(f, want) {
763 t.Errorf("parsed back %#v; want %#v", f, want)
764 }
765 }
766
767 func TestWritePing(t *testing.T) { testWritePing(t, false) }
768 func TestWritePingAck(t *testing.T) { testWritePing(t, true) }
769
770 func testWritePing(t *testing.T, ack bool) {
771 fr, buf := testFramer()
772 if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil {
773 t.Fatal(err)
774 }
775 var wantFlags Flags
776 if ack {
777 wantFlags = FlagPingAck
778 }
779 var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08"
780 if buf.String() != wantEnc {
781 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
782 }
783
784 f, err := fr.ReadFrame()
785 if err != nil {
786 t.Fatal(err)
787 }
788 want := &PingFrame{
789 FrameHeader: FrameHeader{
790 valid: true,
791 Type: 0x6,
792 Flags: wantFlags,
793 Length: 0x8,
794 StreamID: 0,
795 },
796 Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
797 }
798 if !reflect.DeepEqual(f, want) {
799 t.Errorf("parsed back %#v; want %#v", f, want)
800 }
801 }
802
803 func TestReadFrameHeader(t *testing.T) {
804 tests := []struct {
805 in string
806 want FrameHeader
807 }{
808 {in: "\x00\x00\x00" + "\x00" + "\x00" + "\x00\x00\x00\x00", want: FrameHeader{}},
809 {in: "\x01\x02\x03" + "\x04" + "\x05" + "\x06\x07\x08\x09", want: FrameHeader{
810 Length: 66051, Type: 4, Flags: 5, StreamID: 101124105,
811 }},
812
813 {in: "\xff\xff\xff" + "\xff" + "\xff" + "\xff\xff\xff\xff", want: FrameHeader{
814 Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
815 {in: "\xff\xff\xff" + "\xff" + "\xff" + "\x7f\xff\xff\xff", want: FrameHeader{
816 Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
817 }
818 for i, tt := range tests {
819 got, err := readFrameHeader(make([]byte, 9), strings.NewReader(tt.in))
820 if err != nil {
821 t.Errorf("%d. readFrameHeader(%q) = %v", i, tt.in, err)
822 continue
823 }
824 tt.want.valid = true
825 if !got.Equal(tt.want) {
826 t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
827 }
828 }
829 }
830
831 func TestReadWriteFrameHeader(t *testing.T) {
832 tests := []struct {
833 len uint32
834 typ FrameType
835 flags Flags
836 streamID uint32
837 }{
838 {len: 0, typ: 255, flags: 1, streamID: 0},
839 {len: 0, typ: 255, flags: 1, streamID: 1},
840 {len: 0, typ: 255, flags: 1, streamID: 255},
841 {len: 0, typ: 255, flags: 1, streamID: 256},
842 {len: 0, typ: 255, flags: 1, streamID: 65535},
843 {len: 0, typ: 255, flags: 1, streamID: 65536},
844
845 {len: 0, typ: 1, flags: 255, streamID: 1},
846 {len: 255, typ: 1, flags: 255, streamID: 1},
847 {len: 256, typ: 1, flags: 255, streamID: 1},
848 {len: 65535, typ: 1, flags: 255, streamID: 1},
849 {len: 65536, typ: 1, flags: 255, streamID: 1},
850 {len: 16777215, typ: 1, flags: 255, streamID: 1},
851 }
852 for _, tt := range tests {
853 fr, buf := testFramer()
854 fr.startWrite(tt.typ, tt.flags, tt.streamID)
855 fr.writeBytes(make([]byte, tt.len))
856 fr.endWrite()
857 fh, err := ReadFrameHeader(buf)
858 if err != nil {
859 t.Errorf("ReadFrameHeader(%+v) = %v", tt, err)
860 continue
861 }
862 if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID {
863 t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh)
864 }
865 }
866
867 }
868
869 func TestWriteTooLargeFrame(t *testing.T) {
870 fr, _ := testFramer()
871 fr.startWrite(0, 1, 1)
872 fr.writeBytes(make([]byte, 1<<24))
873 err := fr.endWrite()
874 if err != ErrFrameTooLarge {
875 t.Errorf("endWrite = %v; want errFrameTooLarge", err)
876 }
877 }
878
879 func TestWriteGoAway(t *testing.T) {
880 const debug = "foo"
881 fr, buf := testFramer()
882 if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil {
883 t.Fatal(err)
884 }
885 const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug
886 if buf.String() != wantEnc {
887 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
888 }
889 f, err := fr.ReadFrame()
890 if err != nil {
891 t.Fatal(err)
892 }
893 want := &GoAwayFrame{
894 FrameHeader: FrameHeader{
895 valid: true,
896 Type: 0x7,
897 Flags: 0,
898 Length: uint32(4 + 4 + len(debug)),
899 StreamID: 0,
900 },
901 LastStreamID: 0x01020304,
902 ErrCode: 0x05060708,
903 debugData: []byte(debug),
904 }
905 if !reflect.DeepEqual(f, want) {
906 t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
907 }
908 if got := string(f.(*GoAwayFrame).DebugData()); got != debug {
909 t.Errorf("debug data = %q; want %q", got, debug)
910 }
911 }
912
913 func TestWritePushPromise(t *testing.T) {
914 pp := PushPromiseParam{
915 StreamID: 42,
916 PromiseID: 42,
917 BlockFragment: []byte("abc"),
918 }
919 fr, buf := testFramer()
920 if err := fr.WritePushPromise(pp); err != nil {
921 t.Fatal(err)
922 }
923 const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc"
924 if buf.String() != wantEnc {
925 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
926 }
927 f, err := fr.ReadFrame()
928 if err != nil {
929 t.Fatal(err)
930 }
931 _, ok := f.(*PushPromiseFrame)
932 if !ok {
933 t.Fatalf("got %T; want *PushPromiseFrame", f)
934 }
935 want := &PushPromiseFrame{
936 FrameHeader: FrameHeader{
937 valid: true,
938 Type: 0x5,
939 Flags: 0x0,
940 Length: 0x7,
941 StreamID: 42,
942 },
943 PromiseID: 42,
944 headerFragBuf: []byte("abc"),
945 }
946 if !reflect.DeepEqual(f, want) {
947 t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
948 }
949 }
950
951
952 func TestReadFrameOrder(t *testing.T) {
953 head := func(f *Framer, id uint32, end bool) {
954 f.WriteHeaders(HeadersFrameParam{
955 StreamID: id,
956 BlockFragment: []byte("foo"),
957 EndHeaders: end,
958 })
959 }
960 cont := func(f *Framer, id uint32, end bool) {
961 f.WriteContinuation(id, end, []byte("foo"))
962 }
963
964 tests := [...]struct {
965 name string
966 w func(*Framer)
967 atLeast int
968 wantErr string
969 }{
970 0: {
971 w: func(f *Framer) {
972 head(f, 1, true)
973 },
974 },
975 1: {
976 w: func(f *Framer) {
977 head(f, 1, true)
978 head(f, 2, true)
979 },
980 },
981 2: {
982 wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1",
983 w: func(f *Framer) {
984 head(f, 1, false)
985 head(f, 2, true)
986 },
987 },
988 3: {
989 wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1",
990 w: func(f *Framer) {
991 head(f, 1, false)
992 },
993 },
994 4: {
995 w: func(f *Framer) {
996 head(f, 1, false)
997 cont(f, 1, true)
998 head(f, 2, true)
999 },
1000 },
1001 5: {
1002 wantErr: "got CONTINUATION for stream 2; expected stream 1",
1003 w: func(f *Framer) {
1004 head(f, 1, false)
1005 cont(f, 2, true)
1006 head(f, 2, true)
1007 },
1008 },
1009 6: {
1010 wantErr: "unexpected CONTINUATION for stream 1",
1011 w: func(f *Framer) {
1012 cont(f, 1, true)
1013 },
1014 },
1015 7: {
1016 wantErr: "unexpected CONTINUATION for stream 1",
1017 w: func(f *Framer) {
1018 cont(f, 1, false)
1019 },
1020 },
1021 8: {
1022 wantErr: "HEADERS frame with stream ID 0",
1023 w: func(f *Framer) {
1024 head(f, 0, true)
1025 },
1026 },
1027 9: {
1028 wantErr: "unexpected CONTINUATION for stream 0",
1029 w: func(f *Framer) {
1030 cont(f, 0, true)
1031 },
1032 },
1033 10: {
1034 wantErr: "unexpected CONTINUATION for stream 1",
1035 atLeast: 5,
1036 w: func(f *Framer) {
1037 head(f, 1, false)
1038 cont(f, 1, false)
1039 cont(f, 1, false)
1040 cont(f, 1, false)
1041 cont(f, 1, true)
1042 cont(f, 1, false)
1043 },
1044 },
1045 }
1046 for i, tt := range tests {
1047 buf := new(bytes.Buffer)
1048 f := NewFramer(buf, buf)
1049 f.AllowIllegalWrites = true
1050 tt.w(f)
1051 f.WriteData(1, true, nil)
1052
1053 var err error
1054 n := 0
1055 var log bytes.Buffer
1056 for {
1057 var got Frame
1058 got, err = f.ReadFrame()
1059 fmt.Fprintf(&log, " read %v, %v\n", got, err)
1060 if err != nil {
1061 break
1062 }
1063 n++
1064 }
1065 if err == io.EOF {
1066 err = nil
1067 }
1068 ok := tt.wantErr == ""
1069 if ok && err != nil {
1070 t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes())
1071 continue
1072 }
1073 if !ok && err != ConnectionError(ErrCodeProtocol) {
1074 t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes())
1075 continue
1076 }
1077 if !((f.errDetail == nil && tt.wantErr == "") || (fmt.Sprint(f.errDetail) == tt.wantErr)) {
1078 t.Errorf("%d. framer error = %q; want %q\n%s", i, f.errDetail, tt.wantErr, log.Bytes())
1079 }
1080 if n < tt.atLeast {
1081 t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes())
1082 }
1083 }
1084 }
1085
1086 func TestMetaFrameHeader(t *testing.T) {
1087 write := func(f *Framer, frags ...[]byte) {
1088 for i, frag := range frags {
1089 end := (i == len(frags)-1)
1090 if i == 0 {
1091 f.WriteHeaders(HeadersFrameParam{
1092 StreamID: 1,
1093 BlockFragment: frag,
1094 EndHeaders: end,
1095 })
1096 } else {
1097 f.WriteContinuation(1, end, frag)
1098 }
1099 }
1100 }
1101
1102 want := func(flags Flags, length uint32, pairs ...string) *MetaHeadersFrame {
1103 mh := &MetaHeadersFrame{
1104 HeadersFrame: &HeadersFrame{
1105 FrameHeader: FrameHeader{
1106 Type: FrameHeaders,
1107 Flags: flags,
1108 Length: length,
1109 StreamID: 1,
1110 },
1111 },
1112 Fields: []hpack.HeaderField(nil),
1113 }
1114 for len(pairs) > 0 {
1115 mh.Fields = append(mh.Fields, hpack.HeaderField{
1116 Name: pairs[0],
1117 Value: pairs[1],
1118 })
1119 pairs = pairs[2:]
1120 }
1121 return mh
1122 }
1123 truncated := func(mh *MetaHeadersFrame) *MetaHeadersFrame {
1124 mh.Truncated = true
1125 return mh
1126 }
1127
1128 const noFlags Flags = 0
1129
1130 oneKBString := strings.Repeat("a", 1<<10)
1131
1132
1133
1134
1135 var trailerNames []string
1136 for i := range 20 {
1137 trailerNames = append(trailerNames, fmt.Sprintf("x-trailer-%d", i))
1138 }
1139 trailerDecl := strings.Join(trailerNames, ",")
1140
1141 tests := [...]struct {
1142 name string
1143 w func(*Framer)
1144 want any
1145 wantErrReason string
1146 maxHeaderListSize uint32
1147 }{
1148 0: {
1149 name: "single_headers",
1150 w: func(f *Framer) {
1151 all := encodeHeaderRaw(t, ":method", "GET", ":path", "/")
1152 write(f, all)
1153 },
1154 want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"),
1155 },
1156 1: {
1157 name: "with_continuation",
1158 w: func(f *Framer) {
1159 all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
1160 write(f, all[:1], all[1:])
1161 },
1162 want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"),
1163 },
1164 2: {
1165 name: "with_two_continuation",
1166 w: func(f *Framer) {
1167 all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
1168 write(f, all[:2], all[2:4], all[4:])
1169 },
1170 want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"),
1171 },
1172 3: {
1173 name: "big_string_okay",
1174 w: func(f *Framer) {
1175 all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
1176 write(f, all[:2], all[2:])
1177 },
1178 want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString),
1179 },
1180 4: {
1181 name: "big_string_error",
1182 w: func(f *Framer) {
1183 all := encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
1184 write(f, all[:2], all[2:])
1185 },
1186 maxHeaderListSize: (1 << 10) / 2,
1187 want: ConnectionError(ErrCodeCompression),
1188 },
1189 5: {
1190 name: "max_header_list_truncated",
1191 w: func(f *Framer) {
1192 var pairs = []string{":method", "GET", ":path", "/"}
1193 for range 100 {
1194 pairs = append(pairs, "foo", "bar")
1195 }
1196 all := encodeHeaderRaw(t, pairs...)
1197 write(f, all[:2], all[2:])
1198 },
1199 maxHeaderListSize: (1 << 10) / 2,
1200 want: truncated(want(noFlags, 2,
1201 ":method", "GET",
1202 ":path", "/",
1203 "foo", "bar",
1204 "foo", "bar",
1205 "foo", "bar",
1206 "foo", "bar",
1207 "foo", "bar",
1208 "foo", "bar",
1209 "foo", "bar",
1210 "foo", "bar",
1211 "foo", "bar",
1212 "foo", "bar",
1213 "foo", "bar",
1214 )),
1215 },
1216 6: {
1217 name: "pseudo_order",
1218 w: func(f *Framer) {
1219 write(f, encodeHeaderRaw(t,
1220 ":method", "GET",
1221 "foo", "bar",
1222 ":path", "/",
1223 ))
1224 },
1225 want: streamError(1, ErrCodeProtocol),
1226 wantErrReason: "pseudo header field after regular",
1227 },
1228 7: {
1229 name: "pseudo_unknown",
1230 w: func(f *Framer) {
1231 write(f, encodeHeaderRaw(t,
1232 ":unknown", "foo",
1233 "foo", "bar",
1234 ))
1235 },
1236 want: streamError(1, ErrCodeProtocol),
1237 wantErrReason: "invalid pseudo-header \":unknown\"",
1238 },
1239 8: {
1240 name: "pseudo_mix_request_response",
1241 w: func(f *Framer) {
1242 write(f, encodeHeaderRaw(t,
1243 ":method", "GET",
1244 ":status", "100",
1245 ))
1246 },
1247 want: streamError(1, ErrCodeProtocol),
1248 wantErrReason: "mix of request and response pseudo headers",
1249 },
1250 9: {
1251 name: "pseudo_dup",
1252 w: func(f *Framer) {
1253 write(f, encodeHeaderRaw(t,
1254 ":method", "GET",
1255 ":method", "POST",
1256 ))
1257 },
1258 want: streamError(1, ErrCodeProtocol),
1259 wantErrReason: "duplicate pseudo-header \":method\"",
1260 },
1261 10: {
1262 name: "trailer_okay_no_pseudo",
1263 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) },
1264 want: want(FlagHeadersEndHeaders, 8, "foo", "bar"),
1265 },
1266 11: {
1267 name: "invalid_field_name",
1268 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) },
1269 want: streamError(1, ErrCodeProtocol),
1270 wantErrReason: "invalid header field name \"CapitalBad\"",
1271 },
1272 12: {
1273 name: "invalid_field_value",
1274 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) },
1275 want: streamError(1, ErrCodeProtocol),
1276 wantErrReason: `invalid header field value for "key"`,
1277 },
1278 13: {
1279 name: "trailer_declaration_okay",
1280 w: func(f *Framer) {
1281 write(f, encodeHeaderRaw(t, ":method", "GET", ":path", "/", "trailer", trailerDecl))
1282 },
1283 maxHeaderListSize: 1024,
1284 want: want(FlagHeadersEndHeaders, 193,
1285 ":method", "GET",
1286 ":path", "/",
1287 "trailer", trailerDecl,
1288 ),
1289 },
1290 14: {
1291 name: "trailer_declaration_truncated",
1292 w: func(f *Framer) {
1293 write(f, encodeHeaderRaw(t, ":method", "GET", ":path", "/", "trailer", trailerDecl))
1294 },
1295 maxHeaderListSize: 512,
1296 want: truncated(want(FlagHeadersEndHeaders, 193,
1297 ":method", "GET",
1298 ":path", "/",
1299 )),
1300 },
1301 }
1302 for i, tt := range tests {
1303 buf := new(bytes.Buffer)
1304 f := NewFramer(buf, buf)
1305 f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
1306 f.MaxHeaderListSize = tt.maxHeaderListSize
1307 tt.w(f)
1308
1309 name := tt.name
1310 if name == "" {
1311 name = fmt.Sprintf("test index %d", i)
1312 }
1313
1314 var got any
1315 var err error
1316 got, err = f.ReadFrame()
1317 if err != nil {
1318 got = err
1319
1320
1321
1322 if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason {
1323 se.Cause = nil
1324 got = se
1325 }
1326 }
1327 if !reflect.DeepEqual(got, tt.want) {
1328 if mhg, ok := got.(*MetaHeadersFrame); ok {
1329 if mhw, ok := tt.want.(*MetaHeadersFrame); ok {
1330 hg := mhg.HeadersFrame
1331 hw := mhw.HeadersFrame
1332 if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) {
1333 t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw)
1334 }
1335 }
1336 }
1337 str := func(v any) string {
1338 if _, ok := v.(error); ok {
1339 return fmt.Sprintf("error %v", v)
1340 } else {
1341 return fmt.Sprintf("value %#v", v)
1342 }
1343 }
1344 t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want))
1345 }
1346 if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) {
1347 t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason)
1348 }
1349 }
1350 }
1351
1352 func TestSetReuseFrames(t *testing.T) {
1353 fr, buf := testFramer()
1354 fr.SetReuseFrames()
1355
1356
1357
1358 firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1359
1360 for range 10 {
1361 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1362 if df != firstDf {
1363 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1364 }
1365 }
1366
1367 for range 10 {
1368 df := readAndVerifyDataFrame("", 0, fr, buf, t)
1369 if df != firstDf {
1370 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1371 }
1372 }
1373
1374 for range 10 {
1375 df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
1376 if df != firstDf {
1377 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1378 }
1379 }
1380 }
1381
1382 func TestSetReuseFramesMoreThanOnce(t *testing.T) {
1383 fr, buf := testFramer()
1384 fr.SetReuseFrames()
1385
1386 firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1387 fr.SetReuseFrames()
1388
1389 for range 10 {
1390 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1391
1392 fr.SetReuseFrames()
1393 if df != firstDf {
1394 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1395 }
1396 }
1397 }
1398
1399 func TestNoSetReuseFrames(t *testing.T) {
1400 fr, buf := testFramer()
1401 const numNewDataFrames = 10
1402 dfSoFar := make([]any, numNewDataFrames)
1403
1404
1405
1406 for i := range numNewDataFrames {
1407 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1408 for _, item := range dfSoFar {
1409 if df == item {
1410 t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
1411 }
1412 }
1413 dfSoFar[i] = df
1414 }
1415 }
1416
1417 func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
1418 var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
1419 fr.WriteData(streamID, true, []byte(data))
1420 wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
1421 if buf.String() != wantEnc {
1422 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
1423 }
1424 f, err := fr.ReadFrame()
1425 if err != nil {
1426 t.Fatal(err)
1427 }
1428 df, ok := f.(*DataFrame)
1429 if !ok {
1430 t.Fatalf("got %T; want *DataFrame", f)
1431 }
1432 if !bytes.Equal(df.Data(), []byte(data)) {
1433 t.Errorf("got %q; want %q", df.Data(), []byte(data))
1434 }
1435 if f.Header().Flags&1 == 0 {
1436 t.Errorf("didn't see END_STREAM flag")
1437 }
1438 return df
1439 }
1440
1441 func encodeHeaderRaw(t testing.TB, headers ...string) []byte {
1442 var buf bytes.Buffer
1443 enc := hpack.NewEncoder(&buf)
1444 for len(headers) > 0 {
1445 k, v := headers[0], headers[1]
1446 err := enc.WriteField(hpack.HeaderField{Name: k, Value: v})
1447 if err != nil {
1448 t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
1449 }
1450 headers = headers[2:]
1451 }
1452 return buf.Bytes()
1453 }
1454
1455 func TestSettingsDuplicates(t *testing.T) {
1456 tests := []struct {
1457 settings []Setting
1458 want bool
1459 }{
1460 {nil, false},
1461 {[]Setting{{ID: 1}}, false},
1462 {[]Setting{{ID: 1}, {ID: 2}}, false},
1463 {[]Setting{{ID: 1}, {ID: 2}}, false},
1464 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
1465 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
1466 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}}, false},
1467
1468 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 2}}, true},
1469 {[]Setting{{ID: 4}, {ID: 2}, {ID: 3}, {ID: 4}}, true},
1470
1471 {[]Setting{
1472 {ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
1473 {ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
1474 {ID: 9}, {ID: 10}, {ID: 11}, {ID: 12},
1475 }, false},
1476
1477 {[]Setting{
1478 {ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
1479 {ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
1480 {ID: 9}, {ID: 10}, {ID: 11}, {ID: 11},
1481 }, true},
1482 }
1483 for i, tt := range tests {
1484 fr, _ := testFramer()
1485 fr.WriteSettings(tt.settings...)
1486 f, err := fr.ReadFrame()
1487 if err != nil {
1488 t.Fatalf("%d. ReadFrame: %v", i, err)
1489 }
1490 sf := f.(*SettingsFrame)
1491 got := sf.HasDuplicates()
1492 if got != tt.want {
1493 t.Errorf("%d. HasDuplicates = %v; want %v", i, got, tt.want)
1494 }
1495 }
1496
1497 }
1498
1499 func TestTypeFrameParser(t *testing.T) {
1500 if len(frameNames) != len(frameParsers) {
1501 t.Errorf("expected len(frameNames)=%d to equal len(frameParsers)=%d",
1502 len(frameNames), len(frameParsers))
1503 }
1504
1505
1506 unknownFrameType := FrameType(FramePriorityUpdate + 1)
1507 unknownParser := typeFrameParser(unknownFrameType)
1508 frame, err := unknownParser(nil, FrameHeader{}, nil, nil)
1509 if err != nil {
1510 t.Errorf("unknownParser() must not return an error: %v", err)
1511 }
1512 if _, isUnknown := frame.(*UnknownFrame); !isUnknown {
1513 t.Errorf("expected UnknownFrame, got %T", frame)
1514 }
1515 }
1516
1517 func TestReadFrameHeaderAndBody(t *testing.T) {
1518 fr, _ := testFramer()
1519 var streamID uint32 = 1
1520 data := []byte("ABC")
1521 if err := fr.WriteData(streamID, true, data); err != nil {
1522 t.Fatalf("WriteData(%d, true, %q) failed: %v", streamID, data, err)
1523 }
1524
1525 fh, err := fr.ReadFrameHeader()
1526 if err != nil {
1527 t.Fatalf("ReadFrameHeader failed: %v", err)
1528 }
1529 wantHeader := FrameHeader{
1530 Type: FrameData,
1531 Flags: FlagDataEndStream,
1532 Length: 3,
1533 StreamID: 1,
1534 valid: true,
1535 }
1536 if !fh.Equal(wantHeader) {
1537 t.Fatalf("ReadFrameHeader = %+v; want %+v", fh, wantHeader)
1538 }
1539
1540 f, err := fr.ReadFrameForHeader(fh)
1541 if err != nil {
1542 t.Fatalf("ReadFrameForHeader failed: %v", err)
1543 }
1544
1545 if !fh.Equal(f.Header()) {
1546 t.Fatalf("Frame.Header() = %+v; want %+v", f.Header(), fh)
1547 }
1548
1549 df, ok := f.(*DataFrame)
1550 if !ok {
1551 t.Fatalf("got %T; want *DataFrame", f)
1552 }
1553 if got, want := df.Data(), data; !bytes.Equal(got, want) {
1554 t.Errorf("DataFrame.Data() = %q; want %q", string(got), string(want))
1555 }
1556 if got, want := df.StreamEnded(), true; got != want {
1557 t.Errorf("DataFrame.StreamEnded() = %v; want %v", got, want)
1558 }
1559 }
1560
1561 func TestReadFrameHeaderFrameTooLarge(t *testing.T) {
1562 fr, _ := testFramer()
1563 fr.SetMaxReadFrameSize(2)
1564 if err := fr.WriteData(1, true, []byte("ABC")); err != nil {
1565 t.Fatalf("WriteData failed: %v", err)
1566 }
1567 fh, err := fr.ReadFrameHeader()
1568 if gotErr, wantErr := err, ErrFrameTooLarge; gotErr != wantErr {
1569 t.Fatalf("ReadFrameHeader returned error %v; want %v", gotErr, wantErr)
1570 }
1571 if fh.StreamID != 1 {
1572 t.Errorf("ReadFrameHeader = %v, %v; want StreamID 1", fh, err)
1573 }
1574 }
1575
1576 func TestReadFrameHeaderBadFrameOrder(t *testing.T) {
1577 fr, _ := testFramer()
1578 if err := fr.WriteHeaders(HeadersFrameParam{
1579 StreamID: 1,
1580 BlockFragment: []byte("foo"),
1581 EndHeaders: false,
1582 }); err != nil {
1583 t.Fatalf("WriteHeaders failed: %v", err)
1584 }
1585
1586
1587 if err := fr.WriteContinuation(2, true, []byte("foo")); err != nil {
1588 t.Fatalf("WriteContinuation failed: %v", err)
1589 }
1590
1591 fh, err := fr.ReadFrameHeader()
1592 if err != nil {
1593 t.Fatalf("ReadFrameHeader failed: %v", err)
1594 }
1595 if _, err = fr.ReadFrameForHeader(fh); err != nil {
1596 t.Fatalf("ReadFrameForHeader failed: %v", err)
1597 }
1598
1599 if _, err := fr.ReadFrameHeader(); err != ConnectionError(ErrCodeProtocol) {
1600 t.Fatalf("ReadFrameHeader returned error %v; want ConnectionError(ErrCodeProtocol)", err)
1601 }
1602 }
1603
1604 func TestReadFrameForHeaderUnexpectedEOF(t *testing.T) {
1605 fr, b := testFramer()
1606 if err := fr.WriteData(1, true, []byte("ABC")); err != nil {
1607 t.Fatalf("WriteData failed: %v", err)
1608 }
1609
1610 fh, err := fr.ReadFrameHeader()
1611 if err != nil {
1612 t.Fatalf("ReadFrameHeader failed: %v", err)
1613 }
1614
1615
1616 b.Truncate(b.Len() - 1)
1617
1618 _, err = fr.ReadFrameForHeader(fh)
1619 if err != io.ErrUnexpectedEOF {
1620 t.Fatalf("ReadFrameForHeader with short body = %v; want io.ErrUnexpectedEOF", err)
1621 }
1622 }
1623
1624 func TestTypeFrameParserHolePanic(t *testing.T) {
1625
1626 fr, _ := testFramer()
1627 if err := fr.WriteRawFrame(FrameType(0x0a), 0, 1, nil); err != nil {
1628 t.Fatal(err)
1629 }
1630
1631 f, err := fr.ReadFrame()
1632 if err != nil {
1633 t.Fatal(err)
1634 }
1635
1636 if _, ok := f.(*UnknownFrame); !ok {
1637 t.Errorf("got %T; want *UnknownFrame", f)
1638 }
1639 }
1640
View as plain text