Home | History | Annotate | Download | only in websockets
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <string>
      6 #include <vector>
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "net/websockets/websocket_handshake_draft75.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "testing/gmock/include/gmock/gmock.h"
     12 #include "testing/platform_test.h"
     13 
     14 namespace net {
     15 
     16 TEST(WebSocketHandshakeDraft75Test, Connect) {
     17   const std::string kExpectedClientHandshakeMessage =
     18       "GET /demo HTTP/1.1\r\n"
     19       "Upgrade: WebSocket\r\n"
     20       "Connection: Upgrade\r\n"
     21       "Host: example.com\r\n"
     22       "Origin: http://example.com\r\n"
     23       "WebSocket-Protocol: sample\r\n"
     24       "\r\n";
     25 
     26   scoped_ptr<WebSocketHandshakeDraft75> handshake(
     27       new WebSocketHandshakeDraft75(GURL("ws://example.com/demo"),
     28                                     "http://example.com",
     29                                     "ws://example.com/demo",
     30                                     "sample"));
     31   EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
     32   EXPECT_EQ(kExpectedClientHandshakeMessage,
     33             handshake->CreateClientHandshakeMessage());
     34 
     35   const char kResponse[] = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
     36       "Upgrade: WebSocket\r\n"
     37       "Connection: Upgrade\r\n"
     38       "WebSocket-Origin: http://example.com\r\n"
     39       "WebSocket-Location: ws://example.com/demo\r\n"
     40       "WebSocket-Protocol: sample\r\n"
     41       "\r\n";
     42 
     43   EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
     44   // too short
     45   EXPECT_EQ(-1, handshake->ReadServerHandshake(kResponse, 16));
     46   EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
     47   // only status line
     48   EXPECT_EQ(-1, handshake->ReadServerHandshake(
     49       kResponse,
     50       WebSocketHandshakeDraft75::kServerHandshakeHeaderLength));
     51   EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
     52   // by upgrade header
     53   EXPECT_EQ(-1, handshake->ReadServerHandshake(
     54       kResponse,
     55       WebSocketHandshakeDraft75::kServerHandshakeHeaderLength +
     56       WebSocketHandshakeDraft75::kUpgradeHeaderLength));
     57   EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
     58   // by connection header
     59   EXPECT_EQ(-1, handshake->ReadServerHandshake(
     60       kResponse,
     61       WebSocketHandshakeDraft75::kServerHandshakeHeaderLength +
     62       WebSocketHandshakeDraft75::kUpgradeHeaderLength +
     63       WebSocketHandshakeDraft75::kConnectionHeaderLength));
     64   EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
     65 
     66   EXPECT_EQ(-1, handshake->ReadServerHandshake(
     67       kResponse, sizeof(kResponse) - 2));
     68   EXPECT_EQ(WebSocketHandshake::MODE_NORMAL, handshake->mode());
     69 
     70   int handshake_length = strlen(kResponse);
     71   EXPECT_EQ(handshake_length, handshake->ReadServerHandshake(
     72       kResponse, sizeof(kResponse) - 1));  // -1 for terminating \0
     73   EXPECT_EQ(WebSocketHandshake::MODE_CONNECTED, handshake->mode());
     74 }
     75 
     76 TEST(WebSocketHandshakeDraft75Test, ServerSentData) {
     77   const std::string kExpectedClientHandshakeMessage =
     78       "GET /demo HTTP/1.1\r\n"
     79       "Upgrade: WebSocket\r\n"
     80       "Connection: Upgrade\r\n"
     81       "Host: example.com\r\n"
     82       "Origin: http://example.com\r\n"
     83       "WebSocket-Protocol: sample\r\n"
     84       "\r\n";
     85   scoped_ptr<WebSocketHandshakeDraft75> handshake(
     86       new WebSocketHandshakeDraft75(GURL("ws://example.com/demo"),
     87                                     "http://example.com",
     88                                     "ws://example.com/demo",
     89                                     "sample"));
     90   EXPECT_EQ(WebSocketHandshake::MODE_INCOMPLETE, handshake->mode());
     91   EXPECT_EQ(kExpectedClientHandshakeMessage,
     92             handshake->CreateClientHandshakeMessage());
     93 
     94   const char kResponse[] ="HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
     95       "Upgrade: WebSocket\r\n"
     96       "Connection: Upgrade\r\n"
     97       "WebSocket-Origin: http://example.com\r\n"
     98       "WebSocket-Location: ws://example.com/demo\r\n"
     99       "WebSocket-Protocol: sample\r\n"
    100       "\r\n"
    101       "\0Hello\xff";
    102 
    103   int handshake_length = strlen(kResponse);
    104   EXPECT_EQ(handshake_length, handshake->ReadServerHandshake(
    105       kResponse, sizeof(kResponse) - 1));  // -1 for terminating \0
    106   EXPECT_EQ(WebSocketHandshake::MODE_CONNECTED, handshake->mode());
    107 }
    108 
    109 TEST(WebSocketHandshakeDraft75Test, CreateClientHandshakeMessage_Simple) {
    110   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    111       new WebSocketHandshakeDraft75(GURL("ws://example.com/demo"),
    112                                     "http://example.com",
    113                                     "ws://example.com/demo",
    114                                     "sample"));
    115   EXPECT_EQ("GET /demo HTTP/1.1\r\n"
    116             "Upgrade: WebSocket\r\n"
    117             "Connection: Upgrade\r\n"
    118             "Host: example.com\r\n"
    119             "Origin: http://example.com\r\n"
    120             "WebSocket-Protocol: sample\r\n"
    121             "\r\n",
    122             handshake->CreateClientHandshakeMessage());
    123 }
    124 
    125 TEST(WebSocketHandshakeDraft75Test, CreateClientHandshakeMessage_PathAndQuery) {
    126   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    127       new WebSocketHandshakeDraft75(GURL("ws://example.com/Test?q=xxx&p=%20"),
    128                                     "http://example.com",
    129                                     "ws://example.com/demo",
    130                                     "sample"));
    131   // Path and query should be preserved as-is.
    132   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    133               testing::HasSubstr("GET /Test?q=xxx&p=%20 HTTP/1.1\r\n"));
    134 }
    135 
    136 TEST(WebSocketHandshakeDraft75Test, CreateClientHandshakeMessage_Host) {
    137   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    138       new WebSocketHandshakeDraft75(GURL("ws://Example.Com/demo"),
    139                                     "http://Example.Com",
    140                                     "ws://Example.Com/demo",
    141                                     "sample"));
    142   // Host should be lowercased
    143   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    144               testing::HasSubstr("Host: example.com\r\n"));
    145   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    146               testing::HasSubstr("Origin: http://example.com\r\n"));
    147 }
    148 
    149 TEST(WebSocketHandshakeDraft75Test, CreateClientHandshakeMessage_TrimPort80) {
    150   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    151       new WebSocketHandshakeDraft75(GURL("ws://example.com:80/demo"),
    152                                     "http://example.com",
    153                                     "ws://example.com/demo",
    154                                     "sample"));
    155   // :80 should be trimmed as it's the default port for ws://.
    156   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    157               testing::HasSubstr("Host: example.com\r\n"));
    158 }
    159 
    160 TEST(WebSocketHandshakeDraft75Test, CreateClientHandshakeMessage_TrimPort443) {
    161   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    162       new WebSocketHandshakeDraft75(GURL("wss://example.com:443/demo"),
    163                                     "http://example.com",
    164                                     "wss://example.com/demo",
    165                                     "sample"));
    166   // :443 should be trimmed as it's the default port for wss://.
    167   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    168               testing::HasSubstr("Host: example.com\r\n"));
    169 }
    170 
    171 TEST(WebSocketHandshakeDraft75Test,
    172      CreateClientHandshakeMessage_NonDefaultPortForWs) {
    173   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    174       new WebSocketHandshakeDraft75(GURL("ws://example.com:8080/demo"),
    175                                     "http://example.com",
    176                                     "wss://example.com/demo",
    177                                     "sample"));
    178   // :8080 should be preserved as it's not the default port for ws://.
    179   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    180               testing::HasSubstr("Host: example.com:8080\r\n"));
    181 }
    182 
    183 TEST(WebSocketHandshakeDraft75Test,
    184      CreateClientHandshakeMessage_NonDefaultPortForWss) {
    185   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    186       new WebSocketHandshakeDraft75(GURL("wss://example.com:4443/demo"),
    187                                     "http://example.com",
    188                                     "wss://example.com/demo",
    189                                     "sample"));
    190   // :4443 should be preserved as it's not the default port for wss://.
    191   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    192               testing::HasSubstr("Host: example.com:4443\r\n"));
    193 }
    194 
    195 TEST(WebSocketHandshakeDraft75Test, CreateClientHandshakeMessage_WsBut443) {
    196   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    197       new WebSocketHandshakeDraft75(GURL("ws://example.com:443/demo"),
    198                                     "http://example.com",
    199                                     "ws://example.com/demo",
    200                                     "sample"));
    201   // :443 should be preserved as it's not the default port for ws://.
    202   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    203               testing::HasSubstr("Host: example.com:443\r\n"));
    204 }
    205 
    206 TEST(WebSocketHandshakeDraft75Test, CreateClientHandshakeMessage_WssBut80) {
    207   scoped_ptr<WebSocketHandshakeDraft75> handshake(
    208       new WebSocketHandshakeDraft75(GURL("wss://example.com:80/demo"),
    209                                     "http://example.com",
    210                                     "wss://example.com/demo",
    211                                     "sample"));
    212   // :80 should be preserved as it's not the default port for wss://.
    213   EXPECT_THAT(handshake->CreateClientHandshakeMessage(),
    214               testing::HasSubstr("Host: example.com:80\r\n"));
    215 }
    216 
    217 }  // namespace net
    218