github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/Godeps/_workspace/src/golang.org/x/net/websocket/hybi_test.go (about)

     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.
     4  
     5  package websocket
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"fmt"
    11  	"io"
    12  	"net/http"
    13  	"net/url"
    14  	"strings"
    15  	"testing"
    16  )
    17  
    18  // Test the getNonceAccept function with values in
    19  // http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
    20  func TestSecWebSocketAccept(t *testing.T) {
    21  	nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
    22  	expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
    23  	accept, err := getNonceAccept(nonce)
    24  	if err != nil {
    25  		t.Errorf("getNonceAccept: returned error %v", err)
    26  		return
    27  	}
    28  	if !bytes.Equal(expected, accept) {
    29  		t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
    30  	}
    31  }
    32  
    33  func TestHybiClientHandshake(t *testing.T) {
    34  	b := bytes.NewBuffer([]byte{})
    35  	bw := bufio.NewWriter(b)
    36  	br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
    37  Upgrade: websocket
    38  Connection: Upgrade
    39  Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    40  Sec-WebSocket-Protocol: chat
    41  
    42  `))
    43  	var err error
    44  	config := new(Config)
    45  	config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
    46  	if err != nil {
    47  		t.Fatal("location url", err)
    48  	}
    49  	config.Origin, err = url.ParseRequestURI("http://example.com")
    50  	if err != nil {
    51  		t.Fatal("origin url", err)
    52  	}
    53  	config.Protocol = append(config.Protocol, "chat")
    54  	config.Protocol = append(config.Protocol, "superchat")
    55  	config.Version = ProtocolVersionHybi13
    56  
    57  	config.handshakeData = map[string]string{
    58  		"key": "dGhlIHNhbXBsZSBub25jZQ==",
    59  	}
    60  	err = hybiClientHandshake(config, br, bw)
    61  	if err != nil {
    62  		t.Errorf("handshake failed: %v", err)
    63  	}
    64  	req, err := http.ReadRequest(bufio.NewReader(b))
    65  	if err != nil {
    66  		t.Fatalf("read request: %v", err)
    67  	}
    68  	if req.Method != "GET" {
    69  		t.Errorf("request method expected GET, but got %q", req.Method)
    70  	}
    71  	if req.URL.Path != "/chat" {
    72  		t.Errorf("request path expected /chat, but got %q", req.URL.Path)
    73  	}
    74  	if req.Proto != "HTTP/1.1" {
    75  		t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
    76  	}
    77  	if req.Host != "server.example.com" {
    78  		t.Errorf("request Host expected server.example.com, but got %v", req.Host)
    79  	}
    80  	var expectedHeader = map[string]string{
    81  		"Connection":             "Upgrade",
    82  		"Upgrade":                "websocket",
    83  		"Sec-Websocket-Key":      config.handshakeData["key"],
    84  		"Origin":                 config.Origin.String(),
    85  		"Sec-Websocket-Protocol": "chat, superchat",
    86  		"Sec-Websocket-Version":  fmt.Sprintf("%d", ProtocolVersionHybi13),
    87  	}
    88  	for k, v := range expectedHeader {
    89  		if req.Header.Get(k) != v {
    90  			t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
    91  		}
    92  	}
    93  }
    94  
    95  func TestHybiClientHandshakeWithHeader(t *testing.T) {
    96  	b := bytes.NewBuffer([]byte{})
    97  	bw := bufio.NewWriter(b)
    98  	br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
    99  Upgrade: websocket
   100  Connection: Upgrade
   101  Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
   102  Sec-WebSocket-Protocol: chat
   103  
   104  `))
   105  	var err error
   106  	config := new(Config)
   107  	config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
   108  	if err != nil {
   109  		t.Fatal("location url", err)
   110  	}
   111  	config.Origin, err = url.ParseRequestURI("http://example.com")
   112  	if err != nil {
   113  		t.Fatal("origin url", err)
   114  	}
   115  	config.Protocol = append(config.Protocol, "chat")
   116  	config.Protocol = append(config.Protocol, "superchat")
   117  	config.Version = ProtocolVersionHybi13
   118  	config.Header = http.Header(make(map[string][]string))
   119  	config.Header.Add("User-Agent", "test")
   120  
   121  	config.handshakeData = map[string]string{
   122  		"key": "dGhlIHNhbXBsZSBub25jZQ==",
   123  	}
   124  	err = hybiClientHandshake(config, br, bw)
   125  	if err != nil {
   126  		t.Errorf("handshake failed: %v", err)
   127  	}
   128  	req, err := http.ReadRequest(bufio.NewReader(b))
   129  	if err != nil {
   130  		t.Fatalf("read request: %v", err)
   131  	}
   132  	if req.Method != "GET" {
   133  		t.Errorf("request method expected GET, but got %q", req.Method)
   134  	}
   135  	if req.URL.Path != "/chat" {
   136  		t.Errorf("request path expected /chat, but got %q", req.URL.Path)
   137  	}
   138  	if req.Proto != "HTTP/1.1" {
   139  		t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
   140  	}
   141  	if req.Host != "server.example.com" {
   142  		t.Errorf("request Host expected server.example.com, but got %v", req.Host)
   143  	}
   144  	var expectedHeader = map[string]string{
   145  		"Connection":             "Upgrade",
   146  		"Upgrade":                "websocket",
   147  		"Sec-Websocket-Key":      config.handshakeData["key"],
   148  		"Origin":                 config.Origin.String(),
   149  		"Sec-Websocket-Protocol": "chat, superchat",
   150  		"Sec-Websocket-Version":  fmt.Sprintf("%d", ProtocolVersionHybi13),
   151  		"User-Agent":             "test",
   152  	}
   153  	for k, v := range expectedHeader {
   154  		if req.Header.Get(k) != v {
   155  			t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
   156  		}
   157  	}
   158  }
   159  
   160  func TestHybiServerHandshake(t *testing.T) {
   161  	config := new(Config)
   162  	handshaker := &hybiServerHandshaker{Config: config}
   163  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   164  Host: server.example.com
   165  Upgrade: websocket
   166  Connection: Upgrade
   167  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   168  Origin: http://example.com
   169  Sec-WebSocket-Protocol: chat, superchat
   170  Sec-WebSocket-Version: 13
   171  
   172  `))
   173  	req, err := http.ReadRequest(br)
   174  	if err != nil {
   175  		t.Fatal("request", err)
   176  	}
   177  	code, err := handshaker.ReadHandshake(br, req)
   178  	if err != nil {
   179  		t.Errorf("handshake failed: %v", err)
   180  	}
   181  	if code != http.StatusSwitchingProtocols {
   182  		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
   183  	}
   184  	expectedProtocols := []string{"chat", "superchat"}
   185  	if fmt.Sprintf("%v", config.Protocol) != fmt.Sprintf("%v", expectedProtocols) {
   186  		t.Errorf("protocol expected %q but got %q", expectedProtocols, config.Protocol)
   187  	}
   188  	b := bytes.NewBuffer([]byte{})
   189  	bw := bufio.NewWriter(b)
   190  
   191  	config.Protocol = config.Protocol[:1]
   192  
   193  	err = handshaker.AcceptHandshake(bw)
   194  	if err != nil {
   195  		t.Errorf("handshake response failed: %v", err)
   196  	}
   197  	expectedResponse := strings.Join([]string{
   198  		"HTTP/1.1 101 Switching Protocols",
   199  		"Upgrade: websocket",
   200  		"Connection: Upgrade",
   201  		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
   202  		"Sec-WebSocket-Protocol: chat",
   203  		"", ""}, "\r\n")
   204  
   205  	if b.String() != expectedResponse {
   206  		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
   207  	}
   208  }
   209  
   210  func TestHybiServerHandshakeNoSubProtocol(t *testing.T) {
   211  	config := new(Config)
   212  	handshaker := &hybiServerHandshaker{Config: config}
   213  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   214  Host: server.example.com
   215  Upgrade: websocket
   216  Connection: Upgrade
   217  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   218  Origin: http://example.com
   219  Sec-WebSocket-Version: 13
   220  
   221  `))
   222  	req, err := http.ReadRequest(br)
   223  	if err != nil {
   224  		t.Fatal("request", err)
   225  	}
   226  	code, err := handshaker.ReadHandshake(br, req)
   227  	if err != nil {
   228  		t.Errorf("handshake failed: %v", err)
   229  	}
   230  	if code != http.StatusSwitchingProtocols {
   231  		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
   232  	}
   233  	if len(config.Protocol) != 0 {
   234  		t.Errorf("len(config.Protocol) expected 0, but got %q", len(config.Protocol))
   235  	}
   236  	b := bytes.NewBuffer([]byte{})
   237  	bw := bufio.NewWriter(b)
   238  
   239  	err = handshaker.AcceptHandshake(bw)
   240  	if err != nil {
   241  		t.Errorf("handshake response failed: %v", err)
   242  	}
   243  	expectedResponse := strings.Join([]string{
   244  		"HTTP/1.1 101 Switching Protocols",
   245  		"Upgrade: websocket",
   246  		"Connection: Upgrade",
   247  		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
   248  		"", ""}, "\r\n")
   249  
   250  	if b.String() != expectedResponse {
   251  		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
   252  	}
   253  }
   254  
   255  func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
   256  	config := new(Config)
   257  	handshaker := &hybiServerHandshaker{Config: config}
   258  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   259  Host: server.example.com
   260  Upgrade: websocket
   261  Connection: Upgrade
   262  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   263  Sec-WebSocket-Origin: http://example.com
   264  Sec-WebSocket-Protocol: chat, superchat
   265  Sec-WebSocket-Version: 9
   266  
   267  `))
   268  	req, err := http.ReadRequest(br)
   269  	if err != nil {
   270  		t.Fatal("request", err)
   271  	}
   272  	code, err := handshaker.ReadHandshake(br, req)
   273  	if err != ErrBadWebSocketVersion {
   274  		t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
   275  	}
   276  	if code != http.StatusBadRequest {
   277  		t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
   278  	}
   279  }
   280  
   281  func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
   282  	b := bytes.NewBuffer([]byte{})
   283  	frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
   284  	w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
   285  	w.(*hybiFrameWriter).header = frameHeader
   286  	_, err := w.Write(testPayload)
   287  	w.Close()
   288  	if err != nil {
   289  		t.Errorf("Write error %q", err)
   290  	}
   291  	var expectedFrame []byte
   292  	expectedFrame = append(expectedFrame, testHeader...)
   293  	expectedFrame = append(expectedFrame, testMaskedPayload...)
   294  	if !bytes.Equal(expectedFrame, b.Bytes()) {
   295  		t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
   296  	}
   297  	frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
   298  	r, err := frameReaderFactory.NewFrameReader()
   299  	if err != nil {
   300  		t.Errorf("Read error %q", err)
   301  	}
   302  	if header := r.HeaderReader(); header == nil {
   303  		t.Errorf("no header")
   304  	} else {
   305  		actualHeader := make([]byte, r.Len())
   306  		n, err := header.Read(actualHeader)
   307  		if err != nil {
   308  			t.Errorf("Read header error %q", err)
   309  		} else {
   310  			if n < len(testHeader) {
   311  				t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
   312  			}
   313  			if !bytes.Equal(testHeader, actualHeader[:n]) {
   314  				t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
   315  			}
   316  		}
   317  	}
   318  	if trailer := r.TrailerReader(); trailer != nil {
   319  		t.Errorf("unexpected trailer %q", trailer)
   320  	}
   321  	frame := r.(*hybiFrameReader)
   322  	if frameHeader.Fin != frame.header.Fin ||
   323  		frameHeader.OpCode != frame.header.OpCode ||
   324  		len(testPayload) != int(frame.header.Length) {
   325  		t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
   326  	}
   327  	payload := make([]byte, len(testPayload))
   328  	_, err = r.Read(payload)
   329  	if err != nil {
   330  		t.Errorf("read %v", err)
   331  	}
   332  	if !bytes.Equal(testPayload, payload) {
   333  		t.Errorf("payload %q vs %q", testPayload, payload)
   334  	}
   335  }
   336  
   337  func TestHybiShortTextFrame(t *testing.T) {
   338  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
   339  	payload := []byte("hello")
   340  	testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
   341  
   342  	payload = make([]byte, 125)
   343  	testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
   344  }
   345  
   346  func TestHybiShortMaskedTextFrame(t *testing.T) {
   347  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
   348  		MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
   349  	payload := []byte("hello")
   350  	maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
   351  	header := []byte{0x81, 0x85}
   352  	header = append(header, frameHeader.MaskingKey...)
   353  	testHybiFrame(t, header, payload, maskedPayload, frameHeader)
   354  }
   355  
   356  func TestHybiShortBinaryFrame(t *testing.T) {
   357  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
   358  	payload := []byte("hello")
   359  	testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
   360  
   361  	payload = make([]byte, 125)
   362  	testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
   363  }
   364  
   365  func TestHybiControlFrame(t *testing.T) {
   366  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
   367  	payload := []byte("hello")
   368  	testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
   369  
   370  	frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
   371  	testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
   372  
   373  	frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
   374  	payload = []byte{0x03, 0xe8} // 1000
   375  	testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
   376  }
   377  
   378  func TestHybiLongFrame(t *testing.T) {
   379  	frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
   380  	payload := make([]byte, 126)
   381  	testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
   382  
   383  	payload = make([]byte, 65535)
   384  	testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
   385  
   386  	payload = make([]byte, 65536)
   387  	testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
   388  }
   389  
   390  func TestHybiClientRead(t *testing.T) {
   391  	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
   392  		0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
   393  		0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
   394  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   395  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   396  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
   397  
   398  	msg := make([]byte, 512)
   399  	n, err := conn.Read(msg)
   400  	if err != nil {
   401  		t.Errorf("read 1st frame, error %q", err)
   402  	}
   403  	if n != 5 {
   404  		t.Errorf("read 1st frame, expect 5, got %d", n)
   405  	}
   406  	if !bytes.Equal(wireData[2:7], msg[:n]) {
   407  		t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
   408  	}
   409  	n, err = conn.Read(msg)
   410  	if err != nil {
   411  		t.Errorf("read 2nd frame, error %q", err)
   412  	}
   413  	if n != 5 {
   414  		t.Errorf("read 2nd frame, expect 5, got %d", n)
   415  	}
   416  	if !bytes.Equal(wireData[16:21], msg[:n]) {
   417  		t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
   418  	}
   419  	n, err = conn.Read(msg)
   420  	if err == nil {
   421  		t.Errorf("read not EOF")
   422  	}
   423  	if n != 0 {
   424  		t.Errorf("expect read 0, got %d", n)
   425  	}
   426  }
   427  
   428  func TestHybiShortRead(t *testing.T) {
   429  	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
   430  		0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
   431  		0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
   432  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   433  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   434  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
   435  
   436  	step := 0
   437  	pos := 0
   438  	expectedPos := []int{2, 5, 16, 19}
   439  	expectedLen := []int{3, 2, 3, 2}
   440  	for {
   441  		msg := make([]byte, 3)
   442  		n, err := conn.Read(msg)
   443  		if step >= len(expectedPos) {
   444  			if err == nil {
   445  				t.Errorf("read not EOF")
   446  			}
   447  			if n != 0 {
   448  				t.Errorf("expect read 0, got %d", n)
   449  			}
   450  			return
   451  		}
   452  		pos = expectedPos[step]
   453  		endPos := pos + expectedLen[step]
   454  		if err != nil {
   455  			t.Errorf("read from %d, got error %q", pos, err)
   456  			return
   457  		}
   458  		if n != endPos-pos {
   459  			t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
   460  		}
   461  		if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
   462  			t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
   463  		}
   464  		step++
   465  	}
   466  }
   467  
   468  func TestHybiServerRead(t *testing.T) {
   469  	wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
   470  		0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
   471  		0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
   472  		0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
   473  		0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
   474  		0x9a, 0xec, 0xc6, 0x48, 0x89, // world
   475  	}
   476  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   477  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   478  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
   479  
   480  	expected := [][]byte{[]byte("hello"), []byte("world")}
   481  
   482  	msg := make([]byte, 512)
   483  	n, err := conn.Read(msg)
   484  	if err != nil {
   485  		t.Errorf("read 1st frame, error %q", err)
   486  	}
   487  	if n != 5 {
   488  		t.Errorf("read 1st frame, expect 5, got %d", n)
   489  	}
   490  	if !bytes.Equal(expected[0], msg[:n]) {
   491  		t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
   492  	}
   493  
   494  	n, err = conn.Read(msg)
   495  	if err != nil {
   496  		t.Errorf("read 2nd frame, error %q", err)
   497  	}
   498  	if n != 5 {
   499  		t.Errorf("read 2nd frame, expect 5, got %d", n)
   500  	}
   501  	if !bytes.Equal(expected[1], msg[:n]) {
   502  		t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
   503  	}
   504  
   505  	n, err = conn.Read(msg)
   506  	if err == nil {
   507  		t.Errorf("read not EOF")
   508  	}
   509  	if n != 0 {
   510  		t.Errorf("expect read 0, got %d", n)
   511  	}
   512  }
   513  
   514  func TestHybiServerReadWithoutMasking(t *testing.T) {
   515  	wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
   516  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   517  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   518  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
   519  	// server MUST close the connection upon receiving a non-masked frame.
   520  	msg := make([]byte, 512)
   521  	_, err := conn.Read(msg)
   522  	if err != io.EOF {
   523  		t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
   524  	}
   525  }
   526  
   527  func TestHybiClientReadWithMasking(t *testing.T) {
   528  	wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
   529  		0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
   530  	}
   531  	br := bufio.NewReader(bytes.NewBuffer(wireData))
   532  	bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
   533  	conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
   534  
   535  	// client MUST close the connection upon receiving a masked frame.
   536  	msg := make([]byte, 512)
   537  	_, err := conn.Read(msg)
   538  	if err != io.EOF {
   539  		t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
   540  	}
   541  }
   542  
   543  // Test the hybiServerHandshaker supports firefox implementation and
   544  // checks Connection request header include (but it's not necessary
   545  // equal to) "upgrade"
   546  func TestHybiServerFirefoxHandshake(t *testing.T) {
   547  	config := new(Config)
   548  	handshaker := &hybiServerHandshaker{Config: config}
   549  	br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
   550  Host: server.example.com
   551  Upgrade: websocket
   552  Connection: keep-alive, upgrade
   553  Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
   554  Origin: http://example.com
   555  Sec-WebSocket-Protocol: chat, superchat
   556  Sec-WebSocket-Version: 13
   557  
   558  `))
   559  	req, err := http.ReadRequest(br)
   560  	if err != nil {
   561  		t.Fatal("request", err)
   562  	}
   563  	code, err := handshaker.ReadHandshake(br, req)
   564  	if err != nil {
   565  		t.Errorf("handshake failed: %v", err)
   566  	}
   567  	if code != http.StatusSwitchingProtocols {
   568  		t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
   569  	}
   570  	b := bytes.NewBuffer([]byte{})
   571  	bw := bufio.NewWriter(b)
   572  
   573  	config.Protocol = []string{"chat"}
   574  
   575  	err = handshaker.AcceptHandshake(bw)
   576  	if err != nil {
   577  		t.Errorf("handshake response failed: %v", err)
   578  	}
   579  	expectedResponse := strings.Join([]string{
   580  		"HTTP/1.1 101 Switching Protocols",
   581  		"Upgrade: websocket",
   582  		"Connection: Upgrade",
   583  		"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
   584  		"Sec-WebSocket-Protocol: chat",
   585  		"", ""}, "\r\n")
   586  
   587  	if b.String() != expectedResponse {
   588  		t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
   589  	}
   590  }