Home | History | Annotate | Download | only in websockets
      1 // Copyright (c) 2012 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 "net/websockets/websocket_handshake_handler.h"
      6 
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/stringprintf.h"
     13 #include "net/http/http_response_headers.h"
     14 #include "net/http/http_util.h"
     15 #include "url/gurl.h"
     16 
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace {
     20 
     21 const char* const kCookieHeaders[] = {
     22   "cookie", "cookie2"
     23 };
     24 
     25 const char* const kSetCookieHeaders[] = {
     26   "set-cookie", "set-cookie2"
     27 };
     28 
     29 // A test fixture to simplify tests for GetKeyNumber().
     30 class WebSocketHandshakeGetKeyNumberTest : public ::testing::Test {
     31  protected:
     32   static const char kExampleFromDraftKey1[];
     33 
     34   // The object is default-initialised with an empty challenge and the example
     35   // key from draft-ietf-hybi-thewebsocketprotocol-00. These can be changed
     36   // using set_challenge() and set_key().
     37   WebSocketHandshakeGetKeyNumberTest()
     38       : challenge_(), key_(kExampleFromDraftKey1) {}
     39 
     40   // A convenience wrapper for the function under test which automatically
     41   // passes in the arguments stored in the object.
     42   void GetKeyNumber() { ::net::internal::GetKeyNumber(key_, &challenge_); }
     43 
     44   // Read current challenge.
     45   const std::string& challenge() const { return challenge_; }
     46 
     47   // Overwrite challenge.
     48   void set_challenge(const std::string& challenge) { challenge_ = challenge; }
     49 
     50   // Reset the challenge to be empty.
     51   void reset_challenge() { challenge_.clear(); }
     52 
     53   // Change key.
     54   void set_key(const std::string& key) { key_ = key; }
     55 
     56  private:
     57   std::string challenge_;
     58   std::string key_;
     59 };
     60 
     61 const char WebSocketHandshakeGetKeyNumberTest::kExampleFromDraftKey1[] =
     62     "3e6b263  4 17 80";
     63 
     64 // A version of the above fixture for death tests.
     65 class WebSocketHandshakeGetKeyNumberDeathTest
     66     : public WebSocketHandshakeGetKeyNumberTest {
     67 };
     68 
     69 }  // namespace
     70 
     71 namespace net {
     72 
     73 TEST(WebSocketHandshakeRequestHandlerTest, SimpleRequest) {
     74   WebSocketHandshakeRequestHandler handler;
     75 
     76   static const char kHandshakeRequestMessage[] =
     77       "GET /demo HTTP/1.1\r\n"
     78       "Host: example.com\r\n"
     79       "Connection: Upgrade\r\n"
     80       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
     81       "Sec-WebSocket-Protocol: sample\r\n"
     82       "Upgrade: WebSocket\r\n"
     83       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
     84       "Origin: http://example.com\r\n"
     85       "\r\n"
     86       "^n:ds[4U";
     87 
     88   EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
     89                                    strlen(kHandshakeRequestMessage)));
     90   EXPECT_EQ(0, handler.protocol_version());
     91 
     92   handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
     93 
     94   EXPECT_EQ(kHandshakeRequestMessage, handler.GetRawRequest());
     95 }
     96 
     97 TEST(WebSocketHandshakeRequestHandlerTest, SimpleRequestHybi06Handshake) {
     98   WebSocketHandshakeRequestHandler handler;
     99 
    100   static const char kHandshakeRequestMessage[] =
    101       "GET /demo HTTP/1.1\r\n"
    102       "Host: example.com\r\n"
    103       "Upgrade: websocket\r\n"
    104       "Connection: Upgrade\r\n"
    105       "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
    106       "Sec-WebSocket-Origin: http://example.com\r\n"
    107       "Sec-WebSocket-Protocol: sample\r\n"
    108       "Sec-WebSocket-Version: 6\r\n"
    109       "\r\n";
    110 
    111   EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
    112                                    strlen(kHandshakeRequestMessage)));
    113   EXPECT_EQ(6, handler.protocol_version());
    114 
    115   handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
    116 
    117   EXPECT_EQ(kHandshakeRequestMessage, handler.GetRawRequest());
    118 }
    119 
    120 TEST(WebSocketHandshakeRequestHandlerTest, ReplaceRequestCookies) {
    121   WebSocketHandshakeRequestHandler handler;
    122 
    123   static const char kHandshakeRequestMessage[] =
    124       "GET /demo HTTP/1.1\r\n"
    125       "Host: example.com\r\n"
    126       "Connection: Upgrade\r\n"
    127       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
    128       "Sec-WebSocket-Protocol: sample\r\n"
    129       "Upgrade: WebSocket\r\n"
    130       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
    131       "Origin: http://example.com\r\n"
    132       "Cookie: WK-websocket-test=1\r\n"
    133       "\r\n"
    134       "^n:ds[4U";
    135 
    136   EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
    137                                    strlen(kHandshakeRequestMessage)));
    138   EXPECT_EQ(0, handler.protocol_version());
    139 
    140   handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
    141 
    142   handler.AppendHeaderIfMissing("Cookie",
    143                                 "WK-websocket-test=1; "
    144                                 "WK-websocket-test-httponly=1");
    145 
    146   static const char kHandshakeRequestExpectedMessage[] =
    147       "GET /demo HTTP/1.1\r\n"
    148       "Host: example.com\r\n"
    149       "Connection: Upgrade\r\n"
    150       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
    151       "Sec-WebSocket-Protocol: sample\r\n"
    152       "Upgrade: WebSocket\r\n"
    153       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
    154       "Origin: http://example.com\r\n"
    155       "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
    156       "\r\n"
    157       "^n:ds[4U";
    158 
    159   EXPECT_EQ(kHandshakeRequestExpectedMessage, handler.GetRawRequest());
    160 }
    161 
    162 TEST(WebSocketHandshakeRequestHandlerTest,
    163      ReplaceRequestCookiesHybi06Handshake) {
    164   WebSocketHandshakeRequestHandler handler;
    165 
    166   static const char kHandshakeRequestMessage[] =
    167       "GET /demo HTTP/1.1\r\n"
    168       "Host: example.com\r\n"
    169       "Upgrade: websocket\r\n"
    170       "Connection: Upgrade\r\n"
    171       "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
    172       "Sec-WebSocket-Origin: http://example.com\r\n"
    173       "Sec-WebSocket-Protocol: sample\r\n"
    174       "Sec-WebSocket-Version: 6\r\n"
    175       "Cookie: WK-websocket-test=1\r\n"
    176       "\r\n";
    177 
    178   EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
    179                                    strlen(kHandshakeRequestMessage)));
    180   EXPECT_EQ(6, handler.protocol_version());
    181 
    182   handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
    183 
    184   handler.AppendHeaderIfMissing("Cookie",
    185                                 "WK-websocket-test=1; "
    186                                 "WK-websocket-test-httponly=1");
    187 
    188   static const char kHandshakeRequestExpectedMessage[] =
    189       "GET /demo HTTP/1.1\r\n"
    190       "Host: example.com\r\n"
    191       "Upgrade: websocket\r\n"
    192       "Connection: Upgrade\r\n"
    193       "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
    194       "Sec-WebSocket-Origin: http://example.com\r\n"
    195       "Sec-WebSocket-Protocol: sample\r\n"
    196       "Sec-WebSocket-Version: 6\r\n"
    197       "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
    198       "\r\n";
    199 
    200   EXPECT_EQ(kHandshakeRequestExpectedMessage, handler.GetRawRequest());
    201 }
    202 
    203 TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponse) {
    204   WebSocketHandshakeResponseHandler handler;
    205   EXPECT_EQ(0, handler.protocol_version());
    206 
    207   static const char kHandshakeResponseMessage[] =
    208       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
    209       "Upgrade: WebSocket\r\n"
    210       "Connection: Upgrade\r\n"
    211       "Sec-WebSocket-Origin: http://example.com\r\n"
    212       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
    213       "Sec-WebSocket-Protocol: sample\r\n"
    214       "\r\n"
    215       "8jKS'y:G*Co,Wxa-";
    216 
    217   EXPECT_EQ(strlen(kHandshakeResponseMessage),
    218             handler.ParseRawResponse(kHandshakeResponseMessage,
    219                                      strlen(kHandshakeResponseMessage)));
    220   EXPECT_TRUE(handler.HasResponse());
    221 
    222   handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
    223 
    224   EXPECT_EQ(kHandshakeResponseMessage, handler.GetResponse());
    225 }
    226 
    227 TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponseHybi06Handshake) {
    228   WebSocketHandshakeResponseHandler handler;
    229   handler.set_protocol_version(6);
    230   EXPECT_EQ(6, handler.protocol_version());
    231 
    232   static const char kHandshakeResponseMessage[] =
    233       "HTTP/1.1 101 Switching Protocols\r\n"
    234       "Upgrade: websocket\r\n"
    235       "Connection: Upgrade\r\n"
    236       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
    237       "Sec-WebSocket-Protocol: sample\r\n"
    238       "\r\n";
    239 
    240   EXPECT_EQ(strlen(kHandshakeResponseMessage),
    241             handler.ParseRawResponse(kHandshakeResponseMessage,
    242                                      strlen(kHandshakeResponseMessage)));
    243   EXPECT_TRUE(handler.HasResponse());
    244 
    245   handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
    246 
    247   EXPECT_EQ(kHandshakeResponseMessage, handler.GetResponse());
    248 }
    249 
    250 TEST(WebSocketHandshakeResponseHandlerTest, ReplaceResponseCookies) {
    251   WebSocketHandshakeResponseHandler handler;
    252   EXPECT_EQ(0, handler.protocol_version());
    253 
    254   static const char kHandshakeResponseMessage[] =
    255       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
    256       "Upgrade: WebSocket\r\n"
    257       "Connection: Upgrade\r\n"
    258       "Sec-WebSocket-Origin: http://example.com\r\n"
    259       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
    260       "Sec-WebSocket-Protocol: sample\r\n"
    261       "Set-Cookie: WK-websocket-test-1\r\n"
    262       "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
    263       "\r\n"
    264       "8jKS'y:G*Co,Wxa-";
    265 
    266   EXPECT_EQ(strlen(kHandshakeResponseMessage),
    267             handler.ParseRawResponse(kHandshakeResponseMessage,
    268                                      strlen(kHandshakeResponseMessage)));
    269   EXPECT_TRUE(handler.HasResponse());
    270   std::vector<std::string> cookies;
    271   handler.GetHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders), &cookies);
    272   ASSERT_EQ(2U, cookies.size());
    273   EXPECT_EQ("WK-websocket-test-1", cookies[0]);
    274   EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies[1]);
    275   handler.RemoveHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders));
    276 
    277   static const char kHandshakeResponseExpectedMessage[] =
    278       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
    279       "Upgrade: WebSocket\r\n"
    280       "Connection: Upgrade\r\n"
    281       "Sec-WebSocket-Origin: http://example.com\r\n"
    282       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
    283       "Sec-WebSocket-Protocol: sample\r\n"
    284       "\r\n"
    285       "8jKS'y:G*Co,Wxa-";
    286 
    287   EXPECT_EQ(kHandshakeResponseExpectedMessage, handler.GetResponse());
    288 }
    289 
    290 TEST(WebSocketHandshakeResponseHandlerTest,
    291      ReplaceResponseCookiesHybi06Handshake) {
    292   WebSocketHandshakeResponseHandler handler;
    293   handler.set_protocol_version(6);
    294   EXPECT_EQ(6, handler.protocol_version());
    295 
    296   static const char kHandshakeResponseMessage[] =
    297       "HTTP/1.1 101 Switching Protocols\r\n"
    298       "Upgrade: websocket\r\n"
    299       "Connection: Upgrade\r\n"
    300       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
    301       "Sec-WebSocket-Protocol: sample\r\n"
    302       "Set-Cookie: WK-websocket-test-1\r\n"
    303       "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
    304       "\r\n";
    305 
    306   EXPECT_EQ(strlen(kHandshakeResponseMessage),
    307             handler.ParseRawResponse(kHandshakeResponseMessage,
    308                                      strlen(kHandshakeResponseMessage)));
    309   EXPECT_TRUE(handler.HasResponse());
    310   std::vector<std::string> cookies;
    311   handler.GetHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders), &cookies);
    312   ASSERT_EQ(2U, cookies.size());
    313   EXPECT_EQ("WK-websocket-test-1", cookies[0]);
    314   EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies[1]);
    315   handler.RemoveHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders));
    316 
    317   static const char kHandshakeResponseExpectedMessage[] =
    318       "HTTP/1.1 101 Switching Protocols\r\n"
    319       "Upgrade: websocket\r\n"
    320       "Connection: Upgrade\r\n"
    321       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
    322       "Sec-WebSocket-Protocol: sample\r\n"
    323       "\r\n";
    324 
    325   EXPECT_EQ(kHandshakeResponseExpectedMessage, handler.GetResponse());
    326 }
    327 
    328 TEST(WebSocketHandshakeResponseHandlerTest, BadResponse) {
    329   WebSocketHandshakeResponseHandler handler;
    330 
    331   static const char kBadMessage[] = "\n\n\r\net-Location: w";
    332   EXPECT_EQ(strlen(kBadMessage),
    333             handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
    334   EXPECT_TRUE(handler.HasResponse());
    335   EXPECT_EQ(kBadMessage, handler.GetResponse());
    336 }
    337 
    338 TEST(WebSocketHandshakeResponseHandlerTest, BadResponse2) {
    339   WebSocketHandshakeResponseHandler handler;
    340 
    341   static const char kBadMessage[] = "\n\r\n\r\net-Location: w";
    342   EXPECT_EQ(strlen(kBadMessage),
    343             handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
    344   EXPECT_TRUE(handler.HasResponse());
    345   EXPECT_EQ(kBadMessage, handler.GetResponse());
    346 }
    347 
    348 TEST(WebSocketHandshakeHandlerTest, HttpRequestResponse) {
    349   WebSocketHandshakeRequestHandler request_handler;
    350 
    351   static const char kHandshakeRequestMessage[] =
    352       "GET /demo HTTP/1.1\r\n"
    353       "Host: example.com\r\n"
    354       "Connection: Upgrade\r\n"
    355       "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
    356       "Sec-WebSocket-Protocol: sample\r\n"
    357       "Upgrade: WebSocket\r\n"
    358       "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
    359       "Origin: http://example.com\r\n"
    360       "\r\n"
    361       "^n:ds[4U";
    362 
    363   EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
    364                                            strlen(kHandshakeRequestMessage)));
    365   EXPECT_EQ(0, request_handler.protocol_version());
    366 
    367   GURL url("ws://example.com/demo");
    368   std::string challenge;
    369   const HttpRequestInfo& request_info =
    370       request_handler.GetRequestInfo(url, &challenge);
    371 
    372   EXPECT_EQ(url, request_info.url);
    373   EXPECT_EQ("GET", request_info.method);
    374   EXPECT_FALSE(request_info.extra_headers.HasHeader("Upgrade"));
    375   EXPECT_FALSE(request_info.extra_headers.HasHeader("Connection"));
    376   EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key1"));
    377   EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key2"));
    378   std::string value;
    379   EXPECT_TRUE(request_info.extra_headers.GetHeader("Host", &value));
    380   EXPECT_EQ("example.com", value);
    381   EXPECT_TRUE(request_info.extra_headers.GetHeader("Origin", &value));
    382   EXPECT_EQ("http://example.com", value);
    383   EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Protocol",
    384                                                    &value));
    385   EXPECT_EQ("sample", value);
    386 
    387   const char expected_challenge[] = "\x31\x6e\x41\x13\x0f\x7e\xd6\x3c^n:ds[4U";
    388 
    389   EXPECT_EQ(expected_challenge, challenge);
    390 
    391   static const char kHandshakeResponseHeader[] =
    392       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
    393       "Sec-WebSocket-Origin: http://example.com\r\n"
    394       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
    395       "Sec-WebSocket-Protocol: sample\r\n";
    396 
    397   std::string raw_headers =
    398       HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader,
    399                                    strlen(kHandshakeResponseHeader));
    400   HttpResponseInfo response_info;
    401   response_info.headers = new HttpResponseHeaders(raw_headers);
    402 
    403   EXPECT_TRUE(StartsWithASCII(response_info.headers->GetStatusLine(),
    404                               "HTTP/1.1 101 ", false));
    405   EXPECT_FALSE(response_info.headers->HasHeader("Upgrade"));
    406   EXPECT_FALSE(response_info.headers->HasHeader("Connection"));
    407   EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Origin",
    408                                                     "http://example.com"));
    409   EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Location",
    410                                                     "ws://example.com/demo"));
    411   EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Protocol",
    412                                                     "sample"));
    413 
    414   WebSocketHandshakeResponseHandler response_handler;
    415   EXPECT_EQ(0, response_handler.protocol_version());
    416   EXPECT_TRUE(response_handler.ParseResponseInfo(response_info, challenge));
    417   EXPECT_TRUE(response_handler.HasResponse());
    418 
    419   static const char kHandshakeResponseExpectedMessage[] =
    420       "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
    421       "Upgrade: WebSocket\r\n"
    422       "Connection: Upgrade\r\n"
    423       "Sec-WebSocket-Origin: http://example.com\r\n"
    424       "Sec-WebSocket-Location: ws://example.com/demo\r\n"
    425       "Sec-WebSocket-Protocol: sample\r\n"
    426       "\r\n"
    427       "8jKS'y:G*Co,Wxa-";
    428 
    429   EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
    430 }
    431 
    432 TEST(WebSocketHandshakeHandlerTest, HttpRequestResponseHybi06Handshake) {
    433   WebSocketHandshakeRequestHandler request_handler;
    434 
    435   static const char kHandshakeRequestMessage[] =
    436       "GET /demo HTTP/1.1\r\n"
    437       "Host: example.com\r\n"
    438       "Upgrade: websocket\r\n"
    439       "Connection: Upgrade\r\n"
    440       "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
    441       "Sec-WebSocket-Origin: http://example.com\r\n"
    442       "Sec-WebSocket-Protocol: sample\r\n"
    443       "Sec-WebSocket-Version: 6\r\n"
    444       "\r\n";
    445 
    446   EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
    447                                            strlen(kHandshakeRequestMessage)));
    448   EXPECT_EQ(6, request_handler.protocol_version());
    449 
    450   GURL url("ws://example.com/demo");
    451   std::string challenge;
    452   const HttpRequestInfo& request_info =
    453       request_handler.GetRequestInfo(url, &challenge);
    454 
    455   EXPECT_EQ(url, request_info.url);
    456   EXPECT_EQ("GET", request_info.method);
    457   EXPECT_FALSE(request_info.extra_headers.HasHeader("Upgrade"));
    458   EXPECT_FALSE(request_info.extra_headers.HasHeader("Connection"));
    459   EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key"));
    460   std::string value;
    461   EXPECT_TRUE(request_info.extra_headers.GetHeader("Host", &value));
    462   EXPECT_EQ("example.com", value);
    463   EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Origin",
    464                                                    &value));
    465   EXPECT_EQ("http://example.com", value);
    466   EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Protocol",
    467                                                    &value));
    468   EXPECT_EQ("sample", value);
    469 
    470   EXPECT_EQ("dGhlIHNhbXBsZSBub25jZQ==", challenge);
    471 
    472   static const char kHandshakeResponseHeader[] =
    473       "HTTP/1.1 101 Switching Protocols\r\n"
    474       "Sec-WebSocket-Protocol: sample\r\n";
    475 
    476   std::string raw_headers =
    477       HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader,
    478                                    strlen(kHandshakeResponseHeader));
    479   HttpResponseInfo response_info;
    480   response_info.headers = new HttpResponseHeaders(raw_headers);
    481 
    482   EXPECT_TRUE(StartsWithASCII(response_info.headers->GetStatusLine(),
    483                               "HTTP/1.1 101 ", false));
    484   EXPECT_FALSE(response_info.headers->HasHeader("Upgrade"));
    485   EXPECT_FALSE(response_info.headers->HasHeader("Connection"));
    486   EXPECT_FALSE(response_info.headers->HasHeader("Sec-WebSocket-Accept"));
    487   EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Protocol",
    488                                                     "sample"));
    489 
    490   WebSocketHandshakeResponseHandler response_handler;
    491   response_handler.set_protocol_version(request_handler.protocol_version());
    492   EXPECT_EQ(6, response_handler.protocol_version());
    493 
    494   EXPECT_TRUE(response_handler.ParseResponseInfo(response_info, challenge));
    495   EXPECT_TRUE(response_handler.HasResponse());
    496 
    497   static const char kHandshakeResponseExpectedMessage[] =
    498       "HTTP/1.1 101 Switching Protocols\r\n"
    499       "Upgrade: websocket\r\n"
    500       "Connection: Upgrade\r\n"
    501       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
    502       "Sec-WebSocket-Protocol: sample\r\n"
    503       "\r\n";
    504 
    505   EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
    506 }
    507 
    508 TEST_F(WebSocketHandshakeGetKeyNumberTest, AppendsToString) {
    509   set_challenge("hello");
    510   GetKeyNumber();
    511   EXPECT_EQ("hello", challenge().substr(0, 5));
    512 }
    513 
    514 TEST_F(WebSocketHandshakeGetKeyNumberTest, AppendsFourBytes) {
    515   set_challenge("hello");
    516   set_key("1 1");
    517   GetKeyNumber();
    518   EXPECT_EQ(9u, challenge().length());
    519 }
    520 
    521 TEST_F(WebSocketHandshakeGetKeyNumberTest, IsBigEndian) {
    522   set_key(base::StringPrintf("%u ", 0x61626364));
    523   GetKeyNumber();
    524   EXPECT_EQ("abcd", challenge());
    525 }
    526 
    527 TEST_F(WebSocketHandshakeGetKeyNumberTest, IgnoresLetters) {
    528   set_key("1b 1");
    529   GetKeyNumber();
    530   char expected_response[] = { 0, 0, 0, 11 };
    531   EXPECT_EQ(std::string(expected_response, 4), challenge());
    532 }
    533 
    534 TEST_F(WebSocketHandshakeGetKeyNumberTest, DividesBySpaces) {
    535   set_key("1 2");
    536   GetKeyNumber();
    537   EXPECT_EQ(12, challenge()[3]);
    538   reset_challenge();
    539   set_key("1  2");
    540   GetKeyNumber();
    541   EXPECT_EQ(6, challenge()[3]);
    542   reset_challenge();
    543   set_key(" 1  2");
    544   GetKeyNumber();
    545   EXPECT_EQ(4, challenge()[3]);
    546   reset_challenge();
    547   set_key(" 1  2 ");
    548   GetKeyNumber();
    549   EXPECT_EQ(3, challenge()[3]);
    550 }
    551 
    552 TEST_F(WebSocketHandshakeGetKeyNumberTest, MatchesExampleFromDraft) {
    553   set_key("3e6b263  4 17 80");
    554   GetKeyNumber();
    555   char expected_response[] = { 0x36, 0x09, 0x65, 0x65 };
    556   EXPECT_EQ(std::string(expected_response, 4), challenge());
    557 }
    558 
    559 TEST_F(WebSocketHandshakeGetKeyNumberTest, Maximum32bitInteger) {
    560   set_key("4294967295 ");
    561   GetKeyNumber();
    562   char expected_response[] = { '\xFF', '\xFF', '\xFF', '\xFF' };
    563   EXPECT_EQ(std::string(expected_response, 4), challenge());
    564 }
    565 
    566 #if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
    567 TEST_F(WebSocketHandshakeGetKeyNumberDeathTest, ThirtyThreeBitIntegerNoGood) {
    568   set_key(" 4294967296");
    569   EXPECT_DEBUG_DEATH(GetKeyNumber(), "overflow");
    570 }
    571 
    572 TEST_F(WebSocketHandshakeGetKeyNumberDeathTest, NoSpacesNoGood) {
    573   set_key("11");
    574   EXPECT_DEBUG_DEATH(GetKeyNumber(), "space");
    575 }
    576 
    577 TEST_F(WebSocketHandshakeGetKeyNumberDeathTest, MustBeIntegralMultiple) {
    578   set_key("1  1");
    579   EXPECT_DEBUG_DEATH(GetKeyNumber(), "spaces");
    580 }
    581 #endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
    582 
    583 }  // namespace net
    584