Commit abb970ef authored by William Chan's avatar William Chan Committed by Brad Fitzpatrick

http/spdy: redo interfaces, flesh out implementation & frame types

Added a new Framer to handle reading/writing Frames. This is necessary since we have to maintain a compression context across streams.

TODO:
* Separate the types and read/write routines into different files.
* Improve error handling.

R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/4503042
parent 4bb337e5
...@@ -6,6 +6,7 @@ include ../../../Make.inc ...@@ -6,6 +6,7 @@ include ../../../Make.inc
TARG=http/spdy TARG=http/spdy
GOFILES=\ GOFILES=\
framer.go\
protocol.go\ protocol.go\
include ../../../Make.pkg include ../../../Make.pkg
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package spdy
import (
"bytes"
"compress/zlib"
"http"
"os"
"testing"
)
type frameIoTest struct {
desc string
data []byte
frame Frame
readError os.Error
readOnly bool
}
var frameIoTests = []frameIoTest{
{
"noop frame",
[]byte{
0x80, 0x02, 0x00, 0x05,
0x00, 0x00, 0x00, 0x00,
},
ControlFrame(
TypeNoop,
0x00,
[]byte{},
),
nil,
false,
},
{
"ping frame",
[]byte{
0x80, 0x02, 0x00, 0x06,
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x01,
},
ControlFrame(
TypePing,
0x00,
[]byte{0x00, 0x00, 0x00, 0x01},
),
nil,
false,
},
{
"syn_stream frame",
[]byte{
0x80, 0x02, 0x00, 0x01,
0x01, 0x00, 0x00, 0x53,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xbb,
0xdf, 0xa2, 0x51, 0xb2,
0x62, 0x60, 0x66, 0x60,
0xcb, 0x4d, 0x2d, 0xc9,
0xc8, 0x4f, 0x61, 0x60,
0x4e, 0x4f, 0x2d, 0x61,
0x60, 0x2e, 0x2d, 0xca,
0x61, 0x10, 0xcb, 0x28,
0x29, 0x29, 0xb0, 0xd2,
0xd7, 0x2f, 0x2f, 0x2f,
0xd7, 0x4b, 0xcf, 0xcf,
0x4f, 0xcf, 0x49, 0xd5,
0x4b, 0xce, 0xcf, 0xd5,
0x67, 0x60, 0x2f, 0x4b,
0x2d, 0x2a, 0xce, 0xcc,
0xcf, 0x63, 0xe0, 0x00,
0x29, 0xd0, 0x37, 0xd4,
0x33, 0x04, 0x00, 0x00,
0x00, 0xff, 0xff,
},
ControlFrame(
TypeSynStream,
0x01,
[]byte{
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xbb,
0xdf, 0xa2, 0x51, 0xb2,
0x62, 0x60, 0x66, 0x60,
0xcb, 0x4d, 0x2d, 0xc9,
0xc8, 0x4f, 0x61, 0x60,
0x4e, 0x4f, 0x2d, 0x61,
0x60, 0x2e, 0x2d, 0xca,
0x61, 0x10, 0xcb, 0x28,
0x29, 0x29, 0xb0, 0xd2,
0xd7, 0x2f, 0x2f, 0x2f,
0xd7, 0x4b, 0xcf, 0xcf,
0x4f, 0xcf, 0x49, 0xd5,
0x4b, 0xce, 0xcf, 0xd5,
0x67, 0x60, 0x2f, 0x4b,
0x2d, 0x2a, 0xce, 0xcc,
0xcf, 0x63, 0xe0, 0x00,
0x29, 0xd0, 0x37, 0xd4,
0x33, 0x04, 0x00, 0x00,
0x00, 0xff, 0xff,
},
),
nil,
false,
},
{
"data frame",
[]byte{
0x00, 0x00, 0x00, 0x05,
0x01, 0x00, 0x00, 0x04,
0x01, 0x02, 0x03, 0x04,
},
DataFrame(
5,
0x01,
[]byte{0x01, 0x02, 0x03, 0x04},
),
nil,
false,
},
{
"too much data",
[]byte{
0x00, 0x00, 0x00, 0x05,
0x01, 0x00, 0x00, 0x04,
0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08,
},
DataFrame(
5,
0x01,
[]byte{0x01, 0x02, 0x03, 0x04},
),
nil,
true,
},
{
"not enough data",
[]byte{
0x00, 0x00, 0x00, 0x05,
},
Frame{},
os.EOF,
true,
},
}
func TestReadFrame(t *testing.T) {
for _, tt := range frameIoTests {
f, err := ReadFrame(bytes.NewBuffer(tt.data))
if err != tt.readError {
t.Errorf("%s: ReadFrame: %s", tt.desc, err)
continue
}
if err == nil {
if !bytes.Equal(f.Header[:], tt.frame.Header[:]) {
t.Errorf("%s: header %q != %q", tt.desc, string(f.Header[:]), string(tt.frame.Header[:]))
}
if f.Flags != tt.frame.Flags {
t.Errorf("%s: flags %#02x != %#02x", tt.desc, f.Flags, tt.frame.Flags)
}
if !bytes.Equal(f.Data, tt.frame.Data) {
t.Errorf("%s: data %q != %q", tt.desc, string(f.Data), string(tt.frame.Data))
}
}
}
}
func TestWriteTo(t *testing.T) {
for _, tt := range frameIoTests {
if tt.readOnly {
continue
}
b := new(bytes.Buffer)
_, err := tt.frame.WriteTo(b)
if err != nil {
t.Errorf("%s: WriteTo: %s", tt.desc, err)
}
if !bytes.Equal(b.Bytes(), tt.data) {
t.Errorf("%s: data %q != %q", tt.desc, string(b.Bytes()), string(tt.data))
}
}
}
var headerDataTest = []byte{
0x78, 0xbb, 0xdf, 0xa2,
0x51, 0xb2, 0x62, 0x60,
0x66, 0x60, 0xcb, 0x4d,
0x2d, 0xc9, 0xc8, 0x4f,
0x61, 0x60, 0x4e, 0x4f,
0x2d, 0x61, 0x60, 0x2e,
0x2d, 0xca, 0x61, 0x10,
0xcb, 0x28, 0x29, 0x29,
0xb0, 0xd2, 0xd7, 0x2f,
0x2f, 0x2f, 0xd7, 0x4b,
0xcf, 0xcf, 0x4f, 0xcf,
0x49, 0xd5, 0x4b, 0xce,
0xcf, 0xd5, 0x67, 0x60,
0x2f, 0x4b, 0x2d, 0x2a,
0xce, 0xcc, 0xcf, 0x63,
0xe0, 0x00, 0x29, 0xd0,
0x37, 0xd4, 0x33, 0x04,
0x00, 0x00, 0x00, 0xff,
0xff,
}
func TestReadHeader(t *testing.T) {
r := NewHeaderReader()
h, err := r.Decode(headerDataTest)
if err != nil {
t.Fatalf("Error: %v", err)
return
}
if len(h) != 3 {
t.Errorf("Header count = %d (expected 3)", len(h))
}
if h.Get("Url") != "http://www.google.com/" {
t.Errorf("Url: %q != %q", h.Get("Url"), "http://www.google.com/")
}
if h.Get("Method") != "get" {
t.Errorf("Method: %q != %q", h.Get("Method"), "get")
}
if h.Get("Version") != "http/1.1" {
t.Errorf("Version: %q != %q", h.Get("Version"), "http/1.1")
}
}
func TestWriteHeader(t *testing.T) {
for level := zlib.NoCompression; level <= zlib.BestCompression; level++ {
r := NewHeaderReader()
w := NewHeaderWriter(level)
for i := 0; i < 100; i++ {
b := new(bytes.Buffer)
gold := http.Header{
"Url": []string{"http://www.google.com/"},
"Method": []string{"get"},
"Version": []string{"http/1.1"},
}
w.WriteHeader(b, gold)
h, err := r.Decode(b.Bytes())
if err != nil {
t.Errorf("(level=%d i=%d) Error: %v", level, i, err)
return
}
if len(h) != len(gold) {
t.Errorf("(level=%d i=%d) Header count = %d (expected %d)", level, i, len(h), len(gold))
}
for k, _ := range h {
if h.Get(k) != gold.Get(k) {
t.Errorf("(level=%d i=%d) %s: %q != %q", level, i, k, h.Get(k), gold.Get(k))
}
}
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment