1
// Copyright 2011 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.
18
func TestHeaderParsing(t *testing.T) {
19
headers := http.Header{
20
"Url": []string{"http://www.google.com/"},
21
"Method": []string{"get"},
22
"Version": []string{"http/1.1"},
24
var headerValueBlockBuf bytes.Buffer
25
writeHeaderValueBlock(&headerValueBlockBuf, headers)
27
const bogusStreamId = 1
28
newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
30
t.Fatal("parseHeaderValueBlock:", err)
33
if !reflect.DeepEqual(headers, newHeaders) {
34
t.Fatal("got: ", newHeaders, "\nwant: ", headers)
38
func TestCreateParseSynStreamFrame(t *testing.T) {
39
buffer := new(bytes.Buffer)
41
headerCompressionDisabled: true,
43
headerBuf: new(bytes.Buffer),
46
synStreamFrame := SynStreamFrame{
47
CFHeader: ControlFrameHeader{
49
frameType: TypeSynStream,
53
"Url": []string{"http://www.google.com/"},
54
"Method": []string{"get"},
55
"Version": []string{"http/1.1"},
58
if err := framer.WriteFrame(&synStreamFrame); err != nil {
59
t.Fatal("WriteFrame without compression:", err)
61
frame, err := framer.ReadFrame()
63
t.Fatal("ReadFrame without compression:", err)
65
parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
67
t.Fatal("Parsed incorrect frame type:", frame)
69
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
70
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
73
// Test again with compression
75
framer, err = NewFramer(buffer, buffer)
77
t.Fatal("Failed to create new framer:", err)
79
if err := framer.WriteFrame(&synStreamFrame); err != nil {
80
t.Fatal("WriteFrame with compression:", err)
82
frame, err = framer.ReadFrame()
84
t.Fatal("ReadFrame with compression:", err)
86
parsedSynStreamFrame, ok = frame.(*SynStreamFrame)
88
t.Fatal("Parsed incorrect frame type:", frame)
90
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
91
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
95
func TestCreateParseSynReplyFrame(t *testing.T) {
96
buffer := new(bytes.Buffer)
98
headerCompressionDisabled: true,
100
headerBuf: new(bytes.Buffer),
103
synReplyFrame := SynReplyFrame{
104
CFHeader: ControlFrameHeader{
106
frameType: TypeSynReply,
109
Headers: http.Header{
110
"Url": []string{"http://www.google.com/"},
111
"Method": []string{"get"},
112
"Version": []string{"http/1.1"},
115
if err := framer.WriteFrame(&synReplyFrame); err != nil {
116
t.Fatal("WriteFrame without compression:", err)
118
frame, err := framer.ReadFrame()
120
t.Fatal("ReadFrame without compression:", err)
122
parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
124
t.Fatal("Parsed incorrect frame type:", frame)
126
if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
127
t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
130
// Test again with compression
132
framer, err = NewFramer(buffer, buffer)
134
t.Fatal("Failed to create new framer:", err)
136
if err := framer.WriteFrame(&synReplyFrame); err != nil {
137
t.Fatal("WriteFrame with compression:", err)
139
frame, err = framer.ReadFrame()
141
t.Fatal("ReadFrame with compression:", err)
143
parsedSynReplyFrame, ok = frame.(*SynReplyFrame)
145
t.Fatal("Parsed incorrect frame type:", frame)
147
if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
148
t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
152
func TestCreateParseRstStream(t *testing.T) {
153
buffer := new(bytes.Buffer)
154
framer, err := NewFramer(buffer, buffer)
156
t.Fatal("Failed to create new framer:", err)
158
rstStreamFrame := RstStreamFrame{
159
CFHeader: ControlFrameHeader{
161
frameType: TypeRstStream,
164
Status: InvalidStream,
166
if err := framer.WriteFrame(&rstStreamFrame); err != nil {
167
t.Fatal("WriteFrame:", err)
169
frame, err := framer.ReadFrame()
171
t.Fatal("ReadFrame:", err)
173
parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
175
t.Fatal("Parsed incorrect frame type:", frame)
177
if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
178
t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
182
func TestCreateParseSettings(t *testing.T) {
183
buffer := new(bytes.Buffer)
184
framer, err := NewFramer(buffer, buffer)
186
t.Fatal("Failed to create new framer:", err)
188
settingsFrame := SettingsFrame{
189
CFHeader: ControlFrameHeader{
191
frameType: TypeSettings,
193
FlagIdValues: []SettingsFlagIdValue{
194
{FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
195
{FlagSettingsPersisted, SettingsUploadBandwidth, 1},
198
if err := framer.WriteFrame(&settingsFrame); err != nil {
199
t.Fatal("WriteFrame:", err)
201
frame, err := framer.ReadFrame()
203
t.Fatal("ReadFrame:", err)
205
parsedSettingsFrame, ok := frame.(*SettingsFrame)
207
t.Fatal("Parsed incorrect frame type:", frame)
209
if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
210
t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
214
func TestCreateParseNoop(t *testing.T) {
215
buffer := new(bytes.Buffer)
216
framer, err := NewFramer(buffer, buffer)
218
t.Fatal("Failed to create new framer:", err)
220
noopFrame := NoopFrame{
221
CFHeader: ControlFrameHeader{
226
if err := framer.WriteFrame(&noopFrame); err != nil {
227
t.Fatal("WriteFrame:", err)
229
frame, err := framer.ReadFrame()
231
t.Fatal("ReadFrame:", err)
233
parsedNoopFrame, ok := frame.(*NoopFrame)
235
t.Fatal("Parsed incorrect frame type:", frame)
237
if !reflect.DeepEqual(noopFrame, *parsedNoopFrame) {
238
t.Fatal("got: ", *parsedNoopFrame, "\nwant: ", noopFrame)
242
func TestCreateParsePing(t *testing.T) {
243
buffer := new(bytes.Buffer)
244
framer, err := NewFramer(buffer, buffer)
246
t.Fatal("Failed to create new framer:", err)
248
pingFrame := PingFrame{
249
CFHeader: ControlFrameHeader{
255
if err := framer.WriteFrame(&pingFrame); err != nil {
256
t.Fatal("WriteFrame:", err)
258
frame, err := framer.ReadFrame()
260
t.Fatal("ReadFrame:", err)
262
parsedPingFrame, ok := frame.(*PingFrame)
264
t.Fatal("Parsed incorrect frame type:", frame)
266
if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
267
t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
271
func TestCreateParseGoAway(t *testing.T) {
272
buffer := new(bytes.Buffer)
273
framer, err := NewFramer(buffer, buffer)
275
t.Fatal("Failed to create new framer:", err)
277
goAwayFrame := GoAwayFrame{
278
CFHeader: ControlFrameHeader{
280
frameType: TypeGoAway,
282
LastGoodStreamId: 31337,
284
if err := framer.WriteFrame(&goAwayFrame); err != nil {
285
t.Fatal("WriteFrame:", err)
287
frame, err := framer.ReadFrame()
289
t.Fatal("ReadFrame:", err)
291
parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
293
t.Fatal("Parsed incorrect frame type:", frame)
295
if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
296
t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
300
func TestCreateParseHeadersFrame(t *testing.T) {
301
buffer := new(bytes.Buffer)
303
headerCompressionDisabled: true,
305
headerBuf: new(bytes.Buffer),
308
headersFrame := HeadersFrame{
309
CFHeader: ControlFrameHeader{
311
frameType: TypeHeaders,
315
headersFrame.Headers = http.Header{
316
"Url": []string{"http://www.google.com/"},
317
"Method": []string{"get"},
318
"Version": []string{"http/1.1"},
320
if err := framer.WriteFrame(&headersFrame); err != nil {
321
t.Fatal("WriteFrame without compression:", err)
323
frame, err := framer.ReadFrame()
325
t.Fatal("ReadFrame without compression:", err)
327
parsedHeadersFrame, ok := frame.(*HeadersFrame)
329
t.Fatal("Parsed incorrect frame type:", frame)
331
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
332
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
335
// Test again with compression
337
framer, err = NewFramer(buffer, buffer)
338
if err := framer.WriteFrame(&headersFrame); err != nil {
339
t.Fatal("WriteFrame with compression:", err)
341
frame, err = framer.ReadFrame()
343
t.Fatal("ReadFrame with compression:", err)
345
parsedHeadersFrame, ok = frame.(*HeadersFrame)
347
t.Fatal("Parsed incorrect frame type:", frame)
349
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
350
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
354
func TestCreateParseDataFrame(t *testing.T) {
355
buffer := new(bytes.Buffer)
356
framer, err := NewFramer(buffer, buffer)
358
t.Fatal("Failed to create new framer:", err)
360
dataFrame := DataFrame{
362
Data: []byte{'h', 'e', 'l', 'l', 'o'},
364
if err := framer.WriteFrame(&dataFrame); err != nil {
365
t.Fatal("WriteFrame:", err)
367
frame, err := framer.ReadFrame()
369
t.Fatal("ReadFrame:", err)
371
parsedDataFrame, ok := frame.(*DataFrame)
373
t.Fatal("Parsed incorrect frame type:", frame)
375
if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
376
t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
380
func TestCompressionContextAcrossFrames(t *testing.T) {
381
buffer := new(bytes.Buffer)
382
framer, err := NewFramer(buffer, buffer)
384
t.Fatal("Failed to create new framer:", err)
386
headersFrame := HeadersFrame{
387
CFHeader: ControlFrameHeader{
389
frameType: TypeHeaders,
392
Headers: http.Header{
393
"Url": []string{"http://www.google.com/"},
394
"Method": []string{"get"},
395
"Version": []string{"http/1.1"},
398
if err := framer.WriteFrame(&headersFrame); err != nil {
399
t.Fatal("WriteFrame (HEADERS):", err)
401
synStreamFrame := SynStreamFrame{ControlFrameHeader{Version, TypeSynStream, 0, 0}, 2, 0, 0, nil}
402
synStreamFrame.Headers = http.Header{
403
"Url": []string{"http://www.google.com/"},
404
"Method": []string{"get"},
405
"Version": []string{"http/1.1"},
407
if err := framer.WriteFrame(&synStreamFrame); err != nil {
408
t.Fatal("WriteFrame (SYN_STREAM):", err)
410
frame, err := framer.ReadFrame()
412
t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
414
parsedHeadersFrame, ok := frame.(*HeadersFrame)
416
t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
418
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
419
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
421
frame, err = framer.ReadFrame()
423
t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
425
parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
427
t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
429
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
430
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
434
func TestMultipleSPDYFrames(t *testing.T) {
435
// Initialize the framers.
436
pr1, pw1 := io.Pipe()
437
pr2, pw2 := io.Pipe()
438
writer, err := NewFramer(pw1, pr2)
440
t.Fatal("Failed to create writer:", err)
442
reader, err := NewFramer(pw2, pr1)
444
t.Fatal("Failed to create reader:", err)
447
// Set up the frames we're actually transferring.
448
headersFrame := HeadersFrame{
449
CFHeader: ControlFrameHeader{
451
frameType: TypeHeaders,
454
Headers: http.Header{
455
"Url": []string{"http://www.google.com/"},
456
"Method": []string{"get"},
457
"Version": []string{"http/1.1"},
460
synStreamFrame := SynStreamFrame{
461
CFHeader: ControlFrameHeader{
463
frameType: TypeSynStream,
466
Headers: http.Header{
467
"Url": []string{"http://www.google.com/"},
468
"Method": []string{"get"},
469
"Version": []string{"http/1.1"},
473
// Start the goroutines to write the frames.
475
if err := writer.WriteFrame(&headersFrame); err != nil {
476
t.Fatal("WriteFrame (HEADERS): ", err)
478
if err := writer.WriteFrame(&synStreamFrame); err != nil {
479
t.Fatal("WriteFrame (SYN_STREAM): ", err)
483
// Read the frames and verify they look as expected.
484
frame, err := reader.ReadFrame()
486
t.Fatal("ReadFrame (HEADERS): ", err)
488
parsedHeadersFrame, ok := frame.(*HeadersFrame)
490
t.Fatal("Parsed incorrect frame type:", frame)
492
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
493
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
495
frame, err = reader.ReadFrame()
497
t.Fatal("ReadFrame (SYN_STREAM):", err)
499
parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
501
t.Fatal("Parsed incorrect frame type.")
503
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
504
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
508
func TestReadMalformedZlibHeader(t *testing.T) {
509
// These were constructed by corrupting the first byte of the zlib
510
// header after writing.
511
malformedStructs := map[string]string{
512
"SynStreamFrame": "gAIAAQAAABgAAAACAAAAAAAAF/nfolGyYmAAAAAA//8=",
513
"SynReplyFrame": "gAIAAgAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
514
"HeadersFrame": "gAIACAAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
516
for name, bad := range malformedStructs {
517
b, err := base64.StdEncoding.DecodeString(bad)
519
t.Errorf("Unable to decode base64 encoded frame %s: %v", name, err)
521
buf := bytes.NewBuffer(b)
522
reader, err := NewFramer(buf, buf)
524
t.Fatalf("NewFramer: %v", err)
526
_, err = reader.ReadFrame()
527
if err != zlib.ErrHeader {
528
t.Errorf("Frame %s, expected: %#v, actual: %#v", name, zlib.ErrHeader, err)
533
type zeroStream struct {
538
var streamIdZeroFrames = map[string]zeroStream{
540
&SynStreamFrame{StreamId: 0},
541
"gAIAAQAAABgAAAAAAAAAAAAAePnfolGyYmAAAAAA//8=",
544
&SynReplyFrame{StreamId: 0},
545
"gAIAAgAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
548
&RstStreamFrame{StreamId: 0},
549
"gAIAAwAAAAgAAAAAAAAAAA==",
552
&HeadersFrame{StreamId: 0},
553
"gAIACAAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
556
&DataFrame{StreamId: 0},
565
func TestNoZeroStreamId(t *testing.T) {
566
for name, f := range streamIdZeroFrames {
567
b, err := base64.StdEncoding.DecodeString(f.encoded)
569
t.Errorf("Unable to decode base64 encoded frame %s: %v", f, err)
572
framer, err := NewFramer(ioutil.Discard, bytes.NewReader(b))
574
t.Fatalf("NewFramer: %v", err)
576
err = framer.WriteFrame(f.frame)
577
checkZeroStreamId(t, name, "WriteFrame", err)
579
_, err = framer.ReadFrame()
580
checkZeroStreamId(t, name, "ReadFrame", err)
584
func checkZeroStreamId(t *testing.T, frame string, method string, err error) {
586
t.Errorf("%s ZeroStreamId, no error on %s", method, frame)
589
eerr, ok := err.(*Error)
590
if !ok || eerr.Err != ZeroStreamId {
591
t.Errorf("%s ZeroStreamId, incorrect error %#v, frame %s", method, eerr, frame)