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 {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
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 TestWritePriority(t *testing.T) {
429 const streamID = 42
430 tests := []struct {
431 name string
432 priority PriorityParam
433 wantFrame *PriorityFrame
434 }{
435 {
436 "not exclusive",
437 PriorityParam{
438 StreamDep: 2,
439 Exclusive: false,
440 Weight: 127,
441 },
442 &PriorityFrame{
443 FrameHeader{
444 valid: true,
445 StreamID: streamID,
446 Type: FramePriority,
447 Length: 5,
448 },
449 PriorityParam{
450 StreamDep: 2,
451 Exclusive: false,
452 Weight: 127,
453 },
454 },
455 },
456
457 {
458 "exclusive",
459 PriorityParam{
460 StreamDep: 3,
461 Exclusive: true,
462 Weight: 77,
463 },
464 &PriorityFrame{
465 FrameHeader{
466 valid: true,
467 StreamID: streamID,
468 Type: FramePriority,
469 Length: 5,
470 },
471 PriorityParam{
472 StreamDep: 3,
473 Exclusive: true,
474 Weight: 77,
475 },
476 },
477 },
478 }
479 for _, tt := range tests {
480 fr, _ := testFramer()
481 if err := fr.WritePriority(streamID, tt.priority); err != nil {
482 t.Errorf("test %q: %v", tt.name, err)
483 continue
484 }
485 f, err := fr.ReadFrame()
486 if err != nil {
487 t.Errorf("test %q: failed to read the frame back: %v", tt.name, err)
488 continue
489 }
490 if !reflect.DeepEqual(f, tt.wantFrame) {
491 t.Errorf("test %q: mismatch.\n got: %#v\nwant: %#v\n", tt.name, f, tt.wantFrame)
492 }
493 }
494 }
495
496 func TestWriteSettings(t *testing.T) {
497 fr, buf := testFramer()
498 settings := []Setting{{1, 2}, {3, 4}}
499 fr.WriteSettings(settings...)
500 const wantEnc = "\x00\x00\f\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x04"
501 if buf.String() != wantEnc {
502 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
503 }
504 f, err := fr.ReadFrame()
505 if err != nil {
506 t.Fatal(err)
507 }
508 sf, ok := f.(*SettingsFrame)
509 if !ok {
510 t.Fatalf("Got a %T; want a SettingsFrame", f)
511 }
512 var got []Setting
513 sf.ForeachSetting(func(s Setting) error {
514 got = append(got, s)
515 valBack, ok := sf.Value(s.ID)
516 if !ok || valBack != s.Val {
517 t.Errorf("Value(%d) = %v, %v; want %v, true", s.ID, valBack, ok, s.Val)
518 }
519 return nil
520 })
521 if !reflect.DeepEqual(settings, got) {
522 t.Errorf("Read settings %+v != written settings %+v", got, settings)
523 }
524 }
525
526 func TestWriteSettingsAck(t *testing.T) {
527 fr, buf := testFramer()
528 fr.WriteSettingsAck()
529 const wantEnc = "\x00\x00\x00\x04\x01\x00\x00\x00\x00"
530 if buf.String() != wantEnc {
531 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
532 }
533 }
534
535 func TestWriteWindowUpdate(t *testing.T) {
536 fr, buf := testFramer()
537 const streamID = 1<<24 + 2<<16 + 3<<8 + 4
538 const incr = 7<<24 + 6<<16 + 5<<8 + 4
539 if err := fr.WriteWindowUpdate(streamID, incr); err != nil {
540 t.Fatal(err)
541 }
542 const wantEnc = "\x00\x00\x04\x08\x00\x01\x02\x03\x04\x07\x06\x05\x04"
543 if buf.String() != wantEnc {
544 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
545 }
546 f, err := fr.ReadFrame()
547 if err != nil {
548 t.Fatal(err)
549 }
550 want := &WindowUpdateFrame{
551 FrameHeader: FrameHeader{
552 valid: true,
553 Type: 0x8,
554 Flags: 0x0,
555 Length: 0x4,
556 StreamID: 0x1020304,
557 },
558 Increment: 0x7060504,
559 }
560 if !reflect.DeepEqual(f, want) {
561 t.Errorf("parsed back %#v; want %#v", f, want)
562 }
563 }
564
565 func TestWritePing(t *testing.T) { testWritePing(t, false) }
566 func TestWritePingAck(t *testing.T) { testWritePing(t, true) }
567
568 func testWritePing(t *testing.T, ack bool) {
569 fr, buf := testFramer()
570 if err := fr.WritePing(ack, [8]byte{1, 2, 3, 4, 5, 6, 7, 8}); err != nil {
571 t.Fatal(err)
572 }
573 var wantFlags Flags
574 if ack {
575 wantFlags = FlagPingAck
576 }
577 var wantEnc = "\x00\x00\x08\x06" + string(wantFlags) + "\x00\x00\x00\x00" + "\x01\x02\x03\x04\x05\x06\x07\x08"
578 if buf.String() != wantEnc {
579 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
580 }
581
582 f, err := fr.ReadFrame()
583 if err != nil {
584 t.Fatal(err)
585 }
586 want := &PingFrame{
587 FrameHeader: FrameHeader{
588 valid: true,
589 Type: 0x6,
590 Flags: wantFlags,
591 Length: 0x8,
592 StreamID: 0,
593 },
594 Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8},
595 }
596 if !reflect.DeepEqual(f, want) {
597 t.Errorf("parsed back %#v; want %#v", f, want)
598 }
599 }
600
601 func TestReadFrameHeader(t *testing.T) {
602 tests := []struct {
603 in string
604 want FrameHeader
605 }{
606 {in: "\x00\x00\x00" + "\x00" + "\x00" + "\x00\x00\x00\x00", want: FrameHeader{}},
607 {in: "\x01\x02\x03" + "\x04" + "\x05" + "\x06\x07\x08\x09", want: FrameHeader{
608 Length: 66051, Type: 4, Flags: 5, StreamID: 101124105,
609 }},
610
611 {in: "\xff\xff\xff" + "\xff" + "\xff" + "\xff\xff\xff\xff", want: FrameHeader{
612 Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
613 {in: "\xff\xff\xff" + "\xff" + "\xff" + "\x7f\xff\xff\xff", want: FrameHeader{
614 Length: 16777215, Type: 255, Flags: 255, StreamID: 2147483647}},
615 }
616 for i, tt := range tests {
617 got, err := readFrameHeader(make([]byte, 9), strings.NewReader(tt.in))
618 if err != nil {
619 t.Errorf("%d. readFrameHeader(%q) = %v", i, tt.in, err)
620 continue
621 }
622 tt.want.valid = true
623 if !got.Equal(tt.want) {
624 t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
625 }
626 }
627 }
628
629 func TestReadWriteFrameHeader(t *testing.T) {
630 tests := []struct {
631 len uint32
632 typ FrameType
633 flags Flags
634 streamID uint32
635 }{
636 {len: 0, typ: 255, flags: 1, streamID: 0},
637 {len: 0, typ: 255, flags: 1, streamID: 1},
638 {len: 0, typ: 255, flags: 1, streamID: 255},
639 {len: 0, typ: 255, flags: 1, streamID: 256},
640 {len: 0, typ: 255, flags: 1, streamID: 65535},
641 {len: 0, typ: 255, flags: 1, streamID: 65536},
642
643 {len: 0, typ: 1, flags: 255, streamID: 1},
644 {len: 255, typ: 1, flags: 255, streamID: 1},
645 {len: 256, typ: 1, flags: 255, streamID: 1},
646 {len: 65535, typ: 1, flags: 255, streamID: 1},
647 {len: 65536, typ: 1, flags: 255, streamID: 1},
648 {len: 16777215, typ: 1, flags: 255, streamID: 1},
649 }
650 for _, tt := range tests {
651 fr, buf := testFramer()
652 fr.startWrite(tt.typ, tt.flags, tt.streamID)
653 fr.writeBytes(make([]byte, tt.len))
654 fr.endWrite()
655 fh, err := ReadFrameHeader(buf)
656 if err != nil {
657 t.Errorf("ReadFrameHeader(%+v) = %v", tt, err)
658 continue
659 }
660 if fh.Type != tt.typ || fh.Flags != tt.flags || fh.Length != tt.len || fh.StreamID != tt.streamID {
661 t.Errorf("ReadFrameHeader(%+v) = %+v; mismatch", tt, fh)
662 }
663 }
664
665 }
666
667 func TestWriteTooLargeFrame(t *testing.T) {
668 fr, _ := testFramer()
669 fr.startWrite(0, 1, 1)
670 fr.writeBytes(make([]byte, 1<<24))
671 err := fr.endWrite()
672 if err != ErrFrameTooLarge {
673 t.Errorf("endWrite = %v; want errFrameTooLarge", err)
674 }
675 }
676
677 func TestWriteGoAway(t *testing.T) {
678 const debug = "foo"
679 fr, buf := testFramer()
680 if err := fr.WriteGoAway(0x01020304, 0x05060708, []byte(debug)); err != nil {
681 t.Fatal(err)
682 }
683 const wantEnc = "\x00\x00\v\a\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08" + debug
684 if buf.String() != wantEnc {
685 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
686 }
687 f, err := fr.ReadFrame()
688 if err != nil {
689 t.Fatal(err)
690 }
691 want := &GoAwayFrame{
692 FrameHeader: FrameHeader{
693 valid: true,
694 Type: 0x7,
695 Flags: 0,
696 Length: uint32(4 + 4 + len(debug)),
697 StreamID: 0,
698 },
699 LastStreamID: 0x01020304,
700 ErrCode: 0x05060708,
701 debugData: []byte(debug),
702 }
703 if !reflect.DeepEqual(f, want) {
704 t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
705 }
706 if got := string(f.(*GoAwayFrame).DebugData()); got != debug {
707 t.Errorf("debug data = %q; want %q", got, debug)
708 }
709 }
710
711 func TestWritePushPromise(t *testing.T) {
712 pp := PushPromiseParam{
713 StreamID: 42,
714 PromiseID: 42,
715 BlockFragment: []byte("abc"),
716 }
717 fr, buf := testFramer()
718 if err := fr.WritePushPromise(pp); err != nil {
719 t.Fatal(err)
720 }
721 const wantEnc = "\x00\x00\x07\x05\x00\x00\x00\x00*\x00\x00\x00*abc"
722 if buf.String() != wantEnc {
723 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
724 }
725 f, err := fr.ReadFrame()
726 if err != nil {
727 t.Fatal(err)
728 }
729 _, ok := f.(*PushPromiseFrame)
730 if !ok {
731 t.Fatalf("got %T; want *PushPromiseFrame", f)
732 }
733 want := &PushPromiseFrame{
734 FrameHeader: FrameHeader{
735 valid: true,
736 Type: 0x5,
737 Flags: 0x0,
738 Length: 0x7,
739 StreamID: 42,
740 },
741 PromiseID: 42,
742 headerFragBuf: []byte("abc"),
743 }
744 if !reflect.DeepEqual(f, want) {
745 t.Fatalf("parsed back:\n%#v\nwant:\n%#v", f, want)
746 }
747 }
748
749
750 func TestReadFrameOrder(t *testing.T) {
751 head := func(f *Framer, id uint32, end bool) {
752 f.WriteHeaders(HeadersFrameParam{
753 StreamID: id,
754 BlockFragment: []byte("foo"),
755 EndHeaders: end,
756 })
757 }
758 cont := func(f *Framer, id uint32, end bool) {
759 f.WriteContinuation(id, end, []byte("foo"))
760 }
761
762 tests := [...]struct {
763 name string
764 w func(*Framer)
765 atLeast int
766 wantErr string
767 }{
768 0: {
769 w: func(f *Framer) {
770 head(f, 1, true)
771 },
772 },
773 1: {
774 w: func(f *Framer) {
775 head(f, 1, true)
776 head(f, 2, true)
777 },
778 },
779 2: {
780 wantErr: "got HEADERS for stream 2; expected CONTINUATION following HEADERS for stream 1",
781 w: func(f *Framer) {
782 head(f, 1, false)
783 head(f, 2, true)
784 },
785 },
786 3: {
787 wantErr: "got DATA for stream 1; expected CONTINUATION following HEADERS for stream 1",
788 w: func(f *Framer) {
789 head(f, 1, false)
790 },
791 },
792 4: {
793 w: func(f *Framer) {
794 head(f, 1, false)
795 cont(f, 1, true)
796 head(f, 2, true)
797 },
798 },
799 5: {
800 wantErr: "got CONTINUATION for stream 2; expected stream 1",
801 w: func(f *Framer) {
802 head(f, 1, false)
803 cont(f, 2, true)
804 head(f, 2, true)
805 },
806 },
807 6: {
808 wantErr: "unexpected CONTINUATION for stream 1",
809 w: func(f *Framer) {
810 cont(f, 1, true)
811 },
812 },
813 7: {
814 wantErr: "unexpected CONTINUATION for stream 1",
815 w: func(f *Framer) {
816 cont(f, 1, false)
817 },
818 },
819 8: {
820 wantErr: "HEADERS frame with stream ID 0",
821 w: func(f *Framer) {
822 head(f, 0, true)
823 },
824 },
825 9: {
826 wantErr: "CONTINUATION frame with stream ID 0",
827 w: func(f *Framer) {
828 cont(f, 0, true)
829 },
830 },
831 10: {
832 wantErr: "unexpected CONTINUATION for stream 1",
833 atLeast: 5,
834 w: func(f *Framer) {
835 head(f, 1, false)
836 cont(f, 1, false)
837 cont(f, 1, false)
838 cont(f, 1, false)
839 cont(f, 1, true)
840 cont(f, 1, false)
841 },
842 },
843 }
844 for i, tt := range tests {
845 buf := new(bytes.Buffer)
846 f := NewFramer(buf, buf)
847 f.AllowIllegalWrites = true
848 tt.w(f)
849 f.WriteData(1, true, nil)
850
851 var err error
852 n := 0
853 var log bytes.Buffer
854 for {
855 var got Frame
856 got, err = f.ReadFrame()
857 fmt.Fprintf(&log, " read %v, %v\n", got, err)
858 if err != nil {
859 break
860 }
861 n++
862 }
863 if err == io.EOF {
864 err = nil
865 }
866 ok := tt.wantErr == ""
867 if ok && err != nil {
868 t.Errorf("%d. after %d good frames, ReadFrame = %v; want success\n%s", i, n, err, log.Bytes())
869 continue
870 }
871 if !ok && err != ConnectionError(ErrCodeProtocol) {
872 t.Errorf("%d. after %d good frames, ReadFrame = %v; want ConnectionError(ErrCodeProtocol)\n%s", i, n, err, log.Bytes())
873 continue
874 }
875 if !((f.errDetail == nil && tt.wantErr == "") || (fmt.Sprint(f.errDetail) == tt.wantErr)) {
876 t.Errorf("%d. framer eror = %q; want %q\n%s", i, f.errDetail, tt.wantErr, log.Bytes())
877 }
878 if n < tt.atLeast {
879 t.Errorf("%d. framer only read %d frames; want at least %d\n%s", i, n, tt.atLeast, log.Bytes())
880 }
881 }
882 }
883
884 func TestMetaFrameHeader(t *testing.T) {
885 write := func(f *Framer, frags ...[]byte) {
886 for i, frag := range frags {
887 end := (i == len(frags)-1)
888 if i == 0 {
889 f.WriteHeaders(HeadersFrameParam{
890 StreamID: 1,
891 BlockFragment: frag,
892 EndHeaders: end,
893 })
894 } else {
895 f.WriteContinuation(1, end, frag)
896 }
897 }
898 }
899
900 want := func(flags Flags, length uint32, pairs ...string) *MetaHeadersFrame {
901 mh := &MetaHeadersFrame{
902 HeadersFrame: &HeadersFrame{
903 FrameHeader: FrameHeader{
904 Type: FrameHeaders,
905 Flags: flags,
906 Length: length,
907 StreamID: 1,
908 },
909 },
910 Fields: []hpack.HeaderField(nil),
911 }
912 for len(pairs) > 0 {
913 mh.Fields = append(mh.Fields, hpack.HeaderField{
914 Name: pairs[0],
915 Value: pairs[1],
916 })
917 pairs = pairs[2:]
918 }
919 return mh
920 }
921 truncated := func(mh *MetaHeadersFrame) *MetaHeadersFrame {
922 mh.Truncated = true
923 return mh
924 }
925
926 const noFlags Flags = 0
927
928 oneKBString := strings.Repeat("a", 1<<10)
929
930 tests := [...]struct {
931 name string
932 w func(*Framer)
933 want interface{}
934 wantErrReason string
935 maxHeaderListSize uint32
936 }{
937 0: {
938 name: "single_headers",
939 w: func(f *Framer) {
940 var he hpackEncoder
941 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/")
942 write(f, all)
943 },
944 want: want(FlagHeadersEndHeaders, 2, ":method", "GET", ":path", "/"),
945 },
946 1: {
947 name: "with_continuation",
948 w: func(f *Framer) {
949 var he hpackEncoder
950 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
951 write(f, all[:1], all[1:])
952 },
953 want: want(noFlags, 1, ":method", "GET", ":path", "/", "foo", "bar"),
954 },
955 2: {
956 name: "with_two_continuation",
957 w: func(f *Framer) {
958 var he hpackEncoder
959 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", "bar")
960 write(f, all[:2], all[2:4], all[4:])
961 },
962 want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", "bar"),
963 },
964 3: {
965 name: "big_string_okay",
966 w: func(f *Framer) {
967 var he hpackEncoder
968 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
969 write(f, all[:2], all[2:])
970 },
971 want: want(noFlags, 2, ":method", "GET", ":path", "/", "foo", oneKBString),
972 },
973 4: {
974 name: "big_string_error",
975 w: func(f *Framer) {
976 var he hpackEncoder
977 all := he.encodeHeaderRaw(t, ":method", "GET", ":path", "/", "foo", oneKBString)
978 write(f, all[:2], all[2:])
979 },
980 maxHeaderListSize: (1 << 10) / 2,
981 want: ConnectionError(ErrCodeCompression),
982 },
983 5: {
984 name: "max_header_list_truncated",
985 w: func(f *Framer) {
986 var he hpackEncoder
987 var pairs = []string{":method", "GET", ":path", "/"}
988 for i := 0; i < 100; i++ {
989 pairs = append(pairs, "foo", "bar")
990 }
991 all := he.encodeHeaderRaw(t, pairs...)
992 write(f, all[:2], all[2:])
993 },
994 maxHeaderListSize: (1 << 10) / 2,
995 want: truncated(want(noFlags, 2,
996 ":method", "GET",
997 ":path", "/",
998 "foo", "bar",
999 "foo", "bar",
1000 "foo", "bar",
1001 "foo", "bar",
1002 "foo", "bar",
1003 "foo", "bar",
1004 "foo", "bar",
1005 "foo", "bar",
1006 "foo", "bar",
1007 "foo", "bar",
1008 "foo", "bar",
1009 )),
1010 },
1011 6: {
1012 name: "pseudo_order",
1013 w: func(f *Framer) {
1014 write(f, encodeHeaderRaw(t,
1015 ":method", "GET",
1016 "foo", "bar",
1017 ":path", "/",
1018 ))
1019 },
1020 want: streamError(1, ErrCodeProtocol),
1021 wantErrReason: "pseudo header field after regular",
1022 },
1023 7: {
1024 name: "pseudo_unknown",
1025 w: func(f *Framer) {
1026 write(f, encodeHeaderRaw(t,
1027 ":unknown", "foo",
1028 "foo", "bar",
1029 ))
1030 },
1031 want: streamError(1, ErrCodeProtocol),
1032 wantErrReason: "invalid pseudo-header \":unknown\"",
1033 },
1034 8: {
1035 name: "pseudo_mix_request_response",
1036 w: func(f *Framer) {
1037 write(f, encodeHeaderRaw(t,
1038 ":method", "GET",
1039 ":status", "100",
1040 ))
1041 },
1042 want: streamError(1, ErrCodeProtocol),
1043 wantErrReason: "mix of request and response pseudo headers",
1044 },
1045 9: {
1046 name: "pseudo_dup",
1047 w: func(f *Framer) {
1048 write(f, encodeHeaderRaw(t,
1049 ":method", "GET",
1050 ":method", "POST",
1051 ))
1052 },
1053 want: streamError(1, ErrCodeProtocol),
1054 wantErrReason: "duplicate pseudo-header \":method\"",
1055 },
1056 10: {
1057 name: "trailer_okay_no_pseudo",
1058 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "foo", "bar")) },
1059 want: want(FlagHeadersEndHeaders, 8, "foo", "bar"),
1060 },
1061 11: {
1062 name: "invalid_field_name",
1063 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "CapitalBad", "x")) },
1064 want: streamError(1, ErrCodeProtocol),
1065 wantErrReason: "invalid header field name \"CapitalBad\"",
1066 },
1067 12: {
1068 name: "invalid_field_value",
1069 w: func(f *Framer) { write(f, encodeHeaderRaw(t, "key", "bad_null\x00")) },
1070 want: streamError(1, ErrCodeProtocol),
1071 wantErrReason: `invalid header field value for "key"`,
1072 },
1073 }
1074 for i, tt := range tests {
1075 buf := new(bytes.Buffer)
1076 f := NewFramer(buf, buf)
1077 f.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
1078 f.MaxHeaderListSize = tt.maxHeaderListSize
1079 tt.w(f)
1080
1081 name := tt.name
1082 if name == "" {
1083 name = fmt.Sprintf("test index %d", i)
1084 }
1085
1086 var got interface{}
1087 var err error
1088 got, err = f.ReadFrame()
1089 if err != nil {
1090 got = err
1091
1092
1093
1094 if se, ok := err.(StreamError); ok && se.Cause != nil && se.Cause.Error() == tt.wantErrReason {
1095 se.Cause = nil
1096 got = se
1097 }
1098 }
1099 if !reflect.DeepEqual(got, tt.want) {
1100 if mhg, ok := got.(*MetaHeadersFrame); ok {
1101 if mhw, ok := tt.want.(*MetaHeadersFrame); ok {
1102 hg := mhg.HeadersFrame
1103 hw := mhw.HeadersFrame
1104 if hg != nil && hw != nil && !reflect.DeepEqual(*hg, *hw) {
1105 t.Errorf("%s: headers differ:\n got: %+v\nwant: %+v\n", name, *hg, *hw)
1106 }
1107 }
1108 }
1109 str := func(v interface{}) string {
1110 if _, ok := v.(error); ok {
1111 return fmt.Sprintf("error %v", v)
1112 } else {
1113 return fmt.Sprintf("value %#v", v)
1114 }
1115 }
1116 t.Errorf("%s:\n got: %v\nwant: %s", name, str(got), str(tt.want))
1117 }
1118 if tt.wantErrReason != "" && tt.wantErrReason != fmt.Sprint(f.errDetail) {
1119 t.Errorf("%s: got error reason %q; want %q", name, f.errDetail, tt.wantErrReason)
1120 }
1121 }
1122 }
1123
1124 func TestSetReuseFrames(t *testing.T) {
1125 fr, buf := testFramer()
1126 fr.SetReuseFrames()
1127
1128
1129
1130 firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1131
1132 for i := 0; i < 10; i++ {
1133 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1134 if df != firstDf {
1135 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1136 }
1137 }
1138
1139 for i := 0; i < 10; i++ {
1140 df := readAndVerifyDataFrame("", 0, fr, buf, t)
1141 if df != firstDf {
1142 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1143 }
1144 }
1145
1146 for i := 0; i < 10; i++ {
1147 df := readAndVerifyDataFrame("HHH", 3, fr, buf, t)
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
1154 func TestSetReuseFramesMoreThanOnce(t *testing.T) {
1155 fr, buf := testFramer()
1156 fr.SetReuseFrames()
1157
1158 firstDf := readAndVerifyDataFrame("ABC", 3, fr, buf, t)
1159 fr.SetReuseFrames()
1160
1161 for i := 0; i < 10; i++ {
1162 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1163
1164 fr.SetReuseFrames()
1165 if df != firstDf {
1166 t.Errorf("Expected Framer to return references to the same DataFrame. Have %v and %v", &df, &firstDf)
1167 }
1168 }
1169 }
1170
1171 func TestNoSetReuseFrames(t *testing.T) {
1172 fr, buf := testFramer()
1173 const numNewDataFrames = 10
1174 dfSoFar := make([]interface{}, numNewDataFrames)
1175
1176
1177
1178 for i := 0; i < numNewDataFrames; i++ {
1179 df := readAndVerifyDataFrame("XYZ", 3, fr, buf, t)
1180 for _, item := range dfSoFar {
1181 if df == item {
1182 t.Errorf("Expected Framer to return new DataFrames since SetNoReuseFrames not set.")
1183 }
1184 }
1185 dfSoFar[i] = df
1186 }
1187 }
1188
1189 func readAndVerifyDataFrame(data string, length byte, fr *Framer, buf *bytes.Buffer, t *testing.T) *DataFrame {
1190 var streamID uint32 = 1<<24 + 2<<16 + 3<<8 + 4
1191 fr.WriteData(streamID, true, []byte(data))
1192 wantEnc := "\x00\x00" + string(length) + "\x00\x01\x01\x02\x03\x04" + data
1193 if buf.String() != wantEnc {
1194 t.Errorf("encoded as %q; want %q", buf.Bytes(), wantEnc)
1195 }
1196 f, err := fr.ReadFrame()
1197 if err != nil {
1198 t.Fatal(err)
1199 }
1200 df, ok := f.(*DataFrame)
1201 if !ok {
1202 t.Fatalf("got %T; want *DataFrame", f)
1203 }
1204 if !bytes.Equal(df.Data(), []byte(data)) {
1205 t.Errorf("got %q; want %q", df.Data(), []byte(data))
1206 }
1207 if f.Header().Flags&1 == 0 {
1208 t.Errorf("didn't see END_STREAM flag")
1209 }
1210 return df
1211 }
1212
1213 func encodeHeaderRaw(t *testing.T, pairs ...string) []byte {
1214 var he hpackEncoder
1215 return he.encodeHeaderRaw(t, pairs...)
1216 }
1217
1218 func TestSettingsDuplicates(t *testing.T) {
1219 tests := []struct {
1220 settings []Setting
1221 want bool
1222 }{
1223 {nil, false},
1224 {[]Setting{{ID: 1}}, false},
1225 {[]Setting{{ID: 1}, {ID: 2}}, false},
1226 {[]Setting{{ID: 1}, {ID: 2}}, false},
1227 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
1228 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}}, false},
1229 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}}, false},
1230
1231 {[]Setting{{ID: 1}, {ID: 2}, {ID: 3}, {ID: 2}}, true},
1232 {[]Setting{{ID: 4}, {ID: 2}, {ID: 3}, {ID: 4}}, true},
1233
1234 {[]Setting{
1235 {ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
1236 {ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
1237 {ID: 9}, {ID: 10}, {ID: 11}, {ID: 12},
1238 }, false},
1239
1240 {[]Setting{
1241 {ID: 1}, {ID: 2}, {ID: 3}, {ID: 4},
1242 {ID: 5}, {ID: 6}, {ID: 7}, {ID: 8},
1243 {ID: 9}, {ID: 10}, {ID: 11}, {ID: 11},
1244 }, true},
1245 }
1246 for i, tt := range tests {
1247 fr, _ := testFramer()
1248 fr.WriteSettings(tt.settings...)
1249 f, err := fr.ReadFrame()
1250 if err != nil {
1251 t.Fatalf("%d. ReadFrame: %v", i, err)
1252 }
1253 sf := f.(*SettingsFrame)
1254 got := sf.HasDuplicates()
1255 if got != tt.want {
1256 t.Errorf("%d. HasDuplicates = %v; want %v", i, got, tt.want)
1257 }
1258 }
1259
1260 }
1261
View as plain text