// 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)) } } } } }