1
16
17
18
19
20
21 package spdy
22
23 import (
24 "bytes"
25 "compress/zlib"
26 "encoding/base64"
27 "io"
28 "io/ioutil"
29 "net/http"
30 "reflect"
31 "testing"
32 )
33
34 var HeadersFixture = http.Header{
35 "Url": []string{"http://www.google.com/"},
36 "Method": []string{"get"},
37 "Version": []string{"http/1.1"},
38 }
39
40 func TestHeaderParsing(t *testing.T) {
41 var headerValueBlockBuf bytes.Buffer
42 writeHeaderValueBlock(&headerValueBlockBuf, HeadersFixture)
43 const bogusStreamId = 1
44 newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
45 if err != nil {
46 t.Fatal("parseHeaderValueBlock:", err)
47 }
48 if !reflect.DeepEqual(HeadersFixture, newHeaders) {
49 t.Fatal("got: ", newHeaders, "\nwant: ", HeadersFixture)
50 }
51 }
52
53 func TestCreateParseSynStreamFrameCompressionDisable(t *testing.T) {
54 buffer := new(bytes.Buffer)
55
56 framer := &Framer{
57 headerCompressionDisabled: true,
58 w: buffer,
59 headerBuf: new(bytes.Buffer),
60 r: buffer,
61 }
62 synStreamFrame := SynStreamFrame{
63 CFHeader: ControlFrameHeader{
64 version: Version,
65 frameType: TypeSynStream,
66 },
67 StreamId: 2,
68 Headers: HeadersFixture,
69 }
70 if err := framer.WriteFrame(&synStreamFrame); err != nil {
71 t.Fatal("WriteFrame without compression:", err)
72 }
73 frame, err := framer.ReadFrame()
74 if err != nil {
75 t.Fatal("ReadFrame without compression:", err)
76 }
77 parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
78 if !ok {
79 t.Fatal("Parsed incorrect frame type:", frame)
80 }
81 if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
82 t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
83 }
84 }
85
86 func TestCreateParseSynStreamFrameCompressionEnable(t *testing.T) {
87 buffer := new(bytes.Buffer)
88 framer, err := NewFramer(buffer, buffer)
89 synStreamFrame := SynStreamFrame{
90 CFHeader: ControlFrameHeader{
91 version: Version,
92 frameType: TypeSynStream,
93 },
94 StreamId: 2,
95 Headers: HeadersFixture,
96 }
97 if err != nil {
98 t.Fatal("Failed to create new framer:", err)
99 }
100 if err := framer.WriteFrame(&synStreamFrame); err != nil {
101 t.Fatal("WriteFrame with compression:", err)
102 }
103 frame, err := framer.ReadFrame()
104 if err != nil {
105 t.Fatal("ReadFrame with compression:", err)
106 }
107 parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
108 if !ok {
109 t.Fatal("Parsed incorrect frame type:", frame)
110 }
111 if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
112 t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
113 }
114 }
115
116 func TestCreateParseSynReplyFrameCompressionDisable(t *testing.T) {
117 buffer := new(bytes.Buffer)
118 framer := &Framer{
119 headerCompressionDisabled: true,
120 w: buffer,
121 headerBuf: new(bytes.Buffer),
122 r: buffer,
123 }
124 synReplyFrame := SynReplyFrame{
125 CFHeader: ControlFrameHeader{
126 version: Version,
127 frameType: TypeSynReply,
128 },
129 StreamId: 2,
130 Headers: HeadersFixture,
131 }
132 if err := framer.WriteFrame(&synReplyFrame); err != nil {
133 t.Fatal("WriteFrame without compression:", err)
134 }
135 frame, err := framer.ReadFrame()
136 if err != nil {
137 t.Fatal("ReadFrame without compression:", err)
138 }
139 parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
140 if !ok {
141 t.Fatal("Parsed incorrect frame type:", frame)
142 }
143 if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
144 t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
145 }
146 }
147
148 func TestCreateParseSynReplyFrameCompressionEnable(t *testing.T) {
149 buffer := new(bytes.Buffer)
150 framer, err := NewFramer(buffer, buffer)
151 synReplyFrame := SynReplyFrame{
152 CFHeader: ControlFrameHeader{
153 version: Version,
154 frameType: TypeSynReply,
155 },
156 StreamId: 2,
157 Headers: HeadersFixture,
158 }
159 if err != nil {
160 t.Fatal("Failed to create new framer:", err)
161 }
162 if err := framer.WriteFrame(&synReplyFrame); err != nil {
163 t.Fatal("WriteFrame with compression:", err)
164 }
165 frame, err := framer.ReadFrame()
166 if err != nil {
167 t.Fatal("ReadFrame with compression:", err)
168 }
169 parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
170 if !ok {
171 t.Fatal("Parsed incorrect frame type:", frame)
172 }
173 if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
174 t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
175 }
176 }
177
178 func TestCreateParseRstStream(t *testing.T) {
179 buffer := new(bytes.Buffer)
180 framer, err := NewFramer(buffer, buffer)
181 if err != nil {
182 t.Fatal("Failed to create new framer:", err)
183 }
184 rstStreamFrame := RstStreamFrame{
185 CFHeader: ControlFrameHeader{
186 version: Version,
187 frameType: TypeRstStream,
188 },
189 StreamId: 1,
190 Status: InvalidStream,
191 }
192 if err := framer.WriteFrame(&rstStreamFrame); err != nil {
193 t.Fatal("WriteFrame:", err)
194 }
195 frame, err := framer.ReadFrame()
196 if err != nil {
197 t.Fatal("ReadFrame:", err)
198 }
199 parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
200 if !ok {
201 t.Fatal("Parsed incorrect frame type:", frame)
202 }
203 if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
204 t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
205 }
206 }
207
208 func TestCreateParseSettings(t *testing.T) {
209 buffer := new(bytes.Buffer)
210 framer, err := NewFramer(buffer, buffer)
211 if err != nil {
212 t.Fatal("Failed to create new framer:", err)
213 }
214 settingsFrame := SettingsFrame{
215 CFHeader: ControlFrameHeader{
216 version: Version,
217 frameType: TypeSettings,
218 },
219 FlagIdValues: []SettingsFlagIdValue{
220 {FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
221 {FlagSettingsPersisted, SettingsUploadBandwidth, 1},
222 },
223 }
224 if err := framer.WriteFrame(&settingsFrame); err != nil {
225 t.Fatal("WriteFrame:", err)
226 }
227 frame, err := framer.ReadFrame()
228 if err != nil {
229 t.Fatal("ReadFrame:", err)
230 }
231 parsedSettingsFrame, ok := frame.(*SettingsFrame)
232 if !ok {
233 t.Fatal("Parsed incorrect frame type:", frame)
234 }
235 if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
236 t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
237 }
238 }
239
240 func TestCreateParsePing(t *testing.T) {
241 buffer := new(bytes.Buffer)
242 framer, err := NewFramer(buffer, buffer)
243 if err != nil {
244 t.Fatal("Failed to create new framer:", err)
245 }
246 pingFrame := PingFrame{
247 CFHeader: ControlFrameHeader{
248 version: Version,
249 frameType: TypePing,
250 },
251 Id: 31337,
252 }
253 if err := framer.WriteFrame(&pingFrame); err != nil {
254 t.Fatal("WriteFrame:", err)
255 }
256 if pingFrame.CFHeader.Flags != 0 {
257 t.Fatal("Incorrect frame type:", pingFrame)
258 }
259 frame, err := framer.ReadFrame()
260 if err != nil {
261 t.Fatal("ReadFrame:", err)
262 }
263 parsedPingFrame, ok := frame.(*PingFrame)
264 if !ok {
265 t.Fatal("Parsed incorrect frame type:", frame)
266 }
267 if parsedPingFrame.CFHeader.Flags != 0 {
268 t.Fatal("Parsed incorrect frame type:", parsedPingFrame)
269 }
270 if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
271 t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
272 }
273 }
274
275 func TestCreateParseGoAway(t *testing.T) {
276 buffer := new(bytes.Buffer)
277 framer, err := NewFramer(buffer, buffer)
278 if err != nil {
279 t.Fatal("Failed to create new framer:", err)
280 }
281 goAwayFrame := GoAwayFrame{
282 CFHeader: ControlFrameHeader{
283 version: Version,
284 frameType: TypeGoAway,
285 },
286 LastGoodStreamId: 31337,
287 Status: 1,
288 }
289 if err := framer.WriteFrame(&goAwayFrame); err != nil {
290 t.Fatal("WriteFrame:", err)
291 }
292 if goAwayFrame.CFHeader.Flags != 0 {
293 t.Fatal("Incorrect frame type:", goAwayFrame)
294 }
295 if goAwayFrame.CFHeader.length != 8 {
296 t.Fatal("Incorrect frame type:", goAwayFrame)
297 }
298 frame, err := framer.ReadFrame()
299 if err != nil {
300 t.Fatal("ReadFrame:", err)
301 }
302 parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
303 if !ok {
304 t.Fatal("Parsed incorrect frame type:", frame)
305 }
306 if parsedGoAwayFrame.CFHeader.Flags != 0 {
307 t.Fatal("Incorrect frame type:", parsedGoAwayFrame)
308 }
309 if parsedGoAwayFrame.CFHeader.length != 8 {
310 t.Fatal("Incorrect frame type:", parsedGoAwayFrame)
311 }
312 if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
313 t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
314 }
315 }
316
317 func TestCreateParseHeadersFrame(t *testing.T) {
318 buffer := new(bytes.Buffer)
319 framer := &Framer{
320 headerCompressionDisabled: true,
321 w: buffer,
322 headerBuf: new(bytes.Buffer),
323 r: buffer,
324 }
325 headersFrame := HeadersFrame{
326 CFHeader: ControlFrameHeader{
327 version: Version,
328 frameType: TypeHeaders,
329 },
330 StreamId: 2,
331 }
332 headersFrame.Headers = HeadersFixture
333 if err := framer.WriteFrame(&headersFrame); err != nil {
334 t.Fatal("WriteFrame without compression:", err)
335 }
336 frame, err := framer.ReadFrame()
337 if err != nil {
338 t.Fatal("ReadFrame without compression:", err)
339 }
340 parsedHeadersFrame, ok := frame.(*HeadersFrame)
341 if !ok {
342 t.Fatal("Parsed incorrect frame type:", frame)
343 }
344 if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
345 t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
346 }
347 }
348
349 func TestCreateParseHeadersFrameCompressionEnable(t *testing.T) {
350 buffer := new(bytes.Buffer)
351 headersFrame := HeadersFrame{
352 CFHeader: ControlFrameHeader{
353 version: Version,
354 frameType: TypeHeaders,
355 },
356 StreamId: 2,
357 }
358 headersFrame.Headers = HeadersFixture
359
360 framer, err := NewFramer(buffer, buffer)
361 if err != nil {
362 t.Fatal("Failed to create new framer:", err)
363 }
364 if err := framer.WriteFrame(&headersFrame); err != nil {
365 t.Fatal("WriteFrame with compression:", err)
366 }
367 frame, err := framer.ReadFrame()
368 if err != nil {
369 t.Fatal("ReadFrame with compression:", err)
370 }
371 parsedHeadersFrame, ok := frame.(*HeadersFrame)
372 if !ok {
373 t.Fatal("Parsed incorrect frame type:", frame)
374 }
375 if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
376 t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
377 }
378 }
379
380 func TestCreateParseWindowUpdateFrame(t *testing.T) {
381 buffer := new(bytes.Buffer)
382 framer, err := NewFramer(buffer, buffer)
383 if err != nil {
384 t.Fatal("Failed to create new framer:", err)
385 }
386 windowUpdateFrame := WindowUpdateFrame{
387 CFHeader: ControlFrameHeader{
388 version: Version,
389 frameType: TypeWindowUpdate,
390 },
391 StreamId: 31337,
392 DeltaWindowSize: 1,
393 }
394 if err := framer.WriteFrame(&windowUpdateFrame); err != nil {
395 t.Fatal("WriteFrame:", err)
396 }
397 if windowUpdateFrame.CFHeader.Flags != 0 {
398 t.Fatal("Incorrect frame type:", windowUpdateFrame)
399 }
400 if windowUpdateFrame.CFHeader.length != 8 {
401 t.Fatal("Incorrect frame type:", windowUpdateFrame)
402 }
403 frame, err := framer.ReadFrame()
404 if err != nil {
405 t.Fatal("ReadFrame:", err)
406 }
407 parsedWindowUpdateFrame, ok := frame.(*WindowUpdateFrame)
408 if !ok {
409 t.Fatal("Parsed incorrect frame type:", frame)
410 }
411 if parsedWindowUpdateFrame.CFHeader.Flags != 0 {
412 t.Fatal("Incorrect frame type:", parsedWindowUpdateFrame)
413 }
414 if parsedWindowUpdateFrame.CFHeader.length != 8 {
415 t.Fatal("Incorrect frame type:", parsedWindowUpdateFrame)
416 }
417 if !reflect.DeepEqual(windowUpdateFrame, *parsedWindowUpdateFrame) {
418 t.Fatal("got: ", *parsedWindowUpdateFrame, "\nwant: ", windowUpdateFrame)
419 }
420 }
421
422 func TestCreateParseDataFrame(t *testing.T) {
423 buffer := new(bytes.Buffer)
424 framer, err := NewFramer(buffer, buffer)
425 if err != nil {
426 t.Fatal("Failed to create new framer:", err)
427 }
428 dataFrame := DataFrame{
429 StreamId: 1,
430 Data: []byte{'h', 'e', 'l', 'l', 'o'},
431 }
432 if err := framer.WriteFrame(&dataFrame); err != nil {
433 t.Fatal("WriteFrame:", err)
434 }
435 frame, err := framer.ReadFrame()
436 if err != nil {
437 t.Fatal("ReadFrame:", err)
438 }
439 parsedDataFrame, ok := frame.(*DataFrame)
440 if !ok {
441 t.Fatal("Parsed incorrect frame type:", frame)
442 }
443 if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
444 t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
445 }
446 }
447
448 func TestCompressionContextAcrossFrames(t *testing.T) {
449 buffer := new(bytes.Buffer)
450 framer, err := NewFramer(buffer, buffer)
451 if err != nil {
452 t.Fatal("Failed to create new framer:", err)
453 }
454 headersFrame := HeadersFrame{
455 CFHeader: ControlFrameHeader{
456 version: Version,
457 frameType: TypeHeaders,
458 },
459 StreamId: 2,
460 Headers: HeadersFixture,
461 }
462 if err := framer.WriteFrame(&headersFrame); err != nil {
463 t.Fatal("WriteFrame (HEADERS):", err)
464 }
465 synStreamFrame := SynStreamFrame{
466 ControlFrameHeader{
467 Version,
468 TypeSynStream,
469 0,
470 0,
471 },
472 2,
473 0,
474 0,
475 1,
476 nil,
477 }
478 synStreamFrame.Headers = HeadersFixture
479
480 if err := framer.WriteFrame(&synStreamFrame); err != nil {
481 t.Fatal("WriteFrame (SYN_STREAM):", err)
482 }
483 frame, err := framer.ReadFrame()
484 if err != nil {
485 t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
486 }
487 parsedHeadersFrame, ok := frame.(*HeadersFrame)
488 if !ok {
489 t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
490 }
491 if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
492 t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
493 }
494 frame, err = framer.ReadFrame()
495 if err != nil {
496 t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
497 }
498 parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
499 if !ok {
500 t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
501 }
502 if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
503 t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
504 }
505 }
506
507 func TestMultipleSPDYFrames(t *testing.T) {
508
509 pr1, pw1 := io.Pipe()
510 pr2, pw2 := io.Pipe()
511 writer, err := NewFramer(pw1, pr2)
512 if err != nil {
513 t.Fatal("Failed to create writer:", err)
514 }
515 reader, err := NewFramer(pw2, pr1)
516 if err != nil {
517 t.Fatal("Failed to create reader:", err)
518 }
519
520
521 headersFrame := HeadersFrame{
522 CFHeader: ControlFrameHeader{
523 version: Version,
524 frameType: TypeHeaders,
525 },
526 StreamId: 2,
527 Headers: HeadersFixture,
528 }
529 synStreamFrame := SynStreamFrame{
530 CFHeader: ControlFrameHeader{
531 version: Version,
532 frameType: TypeSynStream,
533 },
534 StreamId: 2,
535 Headers: HeadersFixture,
536 }
537
538
539 go func() {
540 if err := writer.WriteFrame(&headersFrame); err != nil {
541 t.Error("WriteFrame (HEADERS):", err)
542 }
543 if err := writer.WriteFrame(&synStreamFrame); err != nil {
544 t.Error("WriteFrame (SYN_STREAM):", err)
545 }
546 }()
547
548
549 frame, err := reader.ReadFrame()
550 if err != nil {
551 t.Fatal("ReadFrame (HEADERS): ", err)
552 }
553 parsedHeadersFrame, ok := frame.(*HeadersFrame)
554 if !ok {
555 t.Fatal("Parsed incorrect frame type:", frame)
556 }
557 if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
558 t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
559 }
560 frame, err = reader.ReadFrame()
561 if err != nil {
562 t.Fatal("ReadFrame (SYN_STREAM):", err)
563 }
564 parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
565 if !ok {
566 t.Fatal("Parsed incorrect frame type.")
567 }
568 if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
569 t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
570 }
571 }
572
573 func TestReadMalformedZlibHeader(t *testing.T) {
574
575
576 malformedStructs := map[string]string{
577 "SynStreamFrame": "gAIAAQAAABgAAAACAAAAAAAAF/nfolGyYmAAAAAA//8=",
578 "SynReplyFrame": "gAIAAgAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
579 "HeadersFrame": "gAIACAAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
580 }
581 for name, bad := range malformedStructs {
582 b, err := base64.StdEncoding.DecodeString(bad)
583 if err != nil {
584 t.Errorf("Unable to decode base64 encoded frame %s: %v", name, err)
585 }
586 buf := bytes.NewBuffer(b)
587 reader, err := NewFramer(buf, buf)
588 if err != nil {
589 t.Fatalf("NewFramer: %v", err)
590 }
591 _, err = reader.ReadFrame()
592 if err != zlib.ErrHeader {
593 t.Errorf("Frame %s, expected: %#v, actual: %#v", name, zlib.ErrHeader, err)
594 }
595 }
596 }
597
598
599
600 type zeroStream struct {
601 frame Frame
602 encoded string
603 }
604
605 var streamIdZeroFrames = map[string]zeroStream{
606 "SynStreamFrame": {
607 &SynStreamFrame{StreamId: 0},
608 "gAIAAQAAABgAAAAAAAAAAAAAePnfolGyYmAAAAAA//8=",
609 },
610 "SynReplyFrame": {
611 &SynReplyFrame{StreamId: 0},
612 "gAIAAgAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
613 },
614 "RstStreamFrame": {
615 &RstStreamFrame{StreamId: 0},
616 "gAIAAwAAAAgAAAAAAAAAAA==",
617 },
618 "HeadersFrame": {
619 &HeadersFrame{StreamId: 0},
620 "gAIACAAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
621 },
622 "DataFrame": {
623 &DataFrame{StreamId: 0},
624 "AAAAAAAAAAA=",
625 },
626 "PingFrame": {
627 &PingFrame{Id: 0},
628 "gAIABgAAAAQAAAAA",
629 },
630 }
631
632 func TestNoZeroStreamId(t *testing.T) {
633 t.Skip("TODO: update to work with SPDY3")
634
635 for name, f := range streamIdZeroFrames {
636 b, err := base64.StdEncoding.DecodeString(f.encoded)
637 if err != nil {
638 t.Errorf("Unable to decode base64 encoded frame %s: %v", f, err)
639 continue
640 }
641 framer, err := NewFramer(ioutil.Discard, bytes.NewReader(b))
642 if err != nil {
643 t.Fatalf("NewFramer: %v", err)
644 }
645 err = framer.WriteFrame(f.frame)
646 checkZeroStreamId(t, name, "WriteFrame", err)
647
648 _, err = framer.ReadFrame()
649 checkZeroStreamId(t, name, "ReadFrame", err)
650 }
651 }
652
653 func checkZeroStreamId(t *testing.T, frame string, method string, err error) {
654 if err == nil {
655 t.Errorf("%s ZeroStreamId, no error on %s", method, frame)
656 return
657 }
658 eerr, ok := err.(*Error)
659 if !ok || eerr.Err != ZeroStreamId {
660 t.Errorf("%s ZeroStreamId, incorrect error %#v, frame %s", method, eerr, frame)
661 }
662 }
663
View as plain text