websocket_stream_test.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_stream.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <algorithm> 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utility> 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <vector> 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_vector.h" 13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/histogram.h" 14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/histogram_samples.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/metrics/statistics_recorder.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/net_errors.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_request_headers.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_response_headers.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/client_socket_handle.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/socket_test_util.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_request_test_util.h" 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_basic_handshake_stream.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_frame.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_request_info.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_response_info.h" 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_handshake_stream_create_helper.h" 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_test_util.h" 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h" 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/origin.h" 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace net { 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef std::pair<std::string, std::string> HeaderKeyValuePair; 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::vector<HeaderKeyValuePair> ToVector(const HttpRequestHeaders& headers) { 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HttpRequestHeaders::Iterator it(headers); 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> result; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (it.GetNext()) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.push_back(HeaderKeyValuePair(it.name(), it.value())); 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::vector<HeaderKeyValuePair> ToVector(const HttpResponseHeaders& headers) { 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void* iter = NULL; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string name, value; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> result; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (headers.EnumerateHeaderLines(&iter, &name, &value)) 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.push_back(HeaderKeyValuePair(name, value)); 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// deterministic key to use in the WebSocket handshake. 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class DeterministicKeyWebSocketHandshakeStreamCreateHelper 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : public WebSocketHandshakeStreamCreateHelper { 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicKeyWebSocketHandshakeStreamCreateHelper( 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStream::ConnectDelegate* connect_delegate, 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& requested_subprotocols) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : WebSocketHandshakeStreamCreateHelper(connect_delegate, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requested_subprotocols) {} 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual WebSocketHandshakeStreamBase* CreateBasicStream( 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<ClientSocketHandle> connection, 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool using_proxy) OVERRIDE { 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketHandshakeStreamCreateHelper::CreateBasicStream(connection.Pass(), 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) using_proxy); 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // This will break in an obvious way if the type created by 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // CreateBasicStream() changes. 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<WebSocketBasicHandshakeStream*>(stream()) 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return stream(); 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class WebSocketStreamCreateTest : public ::testing::Test { 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public: 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStreamCreateTest(): has_failed_(false) {} 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectCustomResponse( 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_url, 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_path, 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_request_headers, 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& response_body) { 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.SetExpectations( 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStandardRequest(socket_path, origin, extra_request_headers), 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) response_body); 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStream(socket_url, sub_protocols, origin); 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // errors like "Unable to perform synchronous IO while stopped" will occur. 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectStandard(const std::string& socket_url, 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_path, 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_request_headers, 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_response_headers) { 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse( 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_url, 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_path, 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) origin, 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) extra_request_headers, 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStandardResponse(extra_response_headers)); 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectRawExpectations( 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_url, 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data) { 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.SetRawExpectations(socket_data.Pass()); 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStream(socket_url, sub_protocols, origin); 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // A wrapper for CreateAndConnectStreamForTesting that knows about our default 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // parameters. 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectStream(const std::string& socket_url, 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin) { 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate( 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new TestConnectDelegate(this)); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStream::ConnectDelegate* delegate = connect_delegate.get(); 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_ = ::net::CreateAndConnectStreamForTesting( 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GURL(socket_url), 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeStreamCreateHelper>( 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicKeyWebSocketHandshakeStreamCreateHelper( 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate, sub_protocols)), 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url::Origin(origin), 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.GetURLRequestContext(), 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BoundNetLog(), 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_delegate.Pass()); 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // A simple function to make the tests more readable. Creates an empty vector. 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static std::vector<std::string> NoSubProtocols() { 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return std::vector<std::string>(); 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& failure_message() const { return failure_message_; } 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_failed() const { return has_failed_; } 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) class TestConnectDelegate : public WebSocketStream::ConnectDelegate { 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit TestConnectDelegate(WebSocketStreamCreateTest* owner) 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : owner_(owner) {} 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void OnSuccess(scoped_ptr<WebSocketStream> stream) OVERRIDE { 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream.swap(owner_->stream_); 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnFailure(const std::string& message) OVERRIDE { 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->has_failed_ = true; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->failure_message_ = message; 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnStartOpeningHandshake( 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE { 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (owner_->request_info_) 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ADD_FAILURE(); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->request_info_ = request.Pass(); 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnFinishOpeningHandshake( 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE { 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (owner_->response_info_) 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ADD_FAILURE(); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->response_info_ = response.Pass(); 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStreamCreateTest* owner_; 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketTestURLRequestContextHost url_request_context_host_; 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStreamRequest> stream_request_; 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only set if the connection succeeded. 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStream> stream_; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only set if the connection failed. 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string failure_message_; 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_failed_; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request_info_; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response_info_; 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// There are enough tests of the Sec-WebSocket-Extensions header that they 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// deserve their own test fixture. 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class WebSocketStreamCreateExtensionTest : public WebSocketStreamCreateTest { 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Performs a standard connect, with the value of the Sec-WebSocket-Extensions 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // header in the response set to |extensions_header_value|. Runs the event 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // loop to allow the connect to complete. 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void CreateAndConnectWithExtensions( 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extensions_header_value) { 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectStandard( 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/testing_path", 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/testing_path", 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass WebSocketStreamCreateUMATest : public ::testing::Test { 215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public: 216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // This enum should match with the enum in Delegate in websocket_stream.cc. 217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch enum HandshakeResult { 218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch INCOMPLETE, 219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CONNECTED, 220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch FAILED, 221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NUM_HANDSHAKE_RESULT_TYPES, 222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }; 223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch class StreamCreation : public WebSocketStreamCreateTest { 225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch virtual void TestBody() OVERRIDE {} 226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch }; 227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> GetSamples(const std::string& name) { 229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::HistogramBase* histogram = 230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::StatisticsRecorder::FindHistogram(name); 231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return histogram ? histogram->SnapshotSamples() 232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : scoped_ptr<base::HistogramSamples>(); 233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}; 235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Confirm that the basic case works as expected. 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(response_info_); 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, HandshakeInfo) { 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kResponse[] = 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: websocket\r\n" 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: Upgrade\r\n" 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "foo: bar, baz\r\n" 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "hoge: fuga\r\n" 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "hoge: piyo\r\n" 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse( 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/", 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kResponse); 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(request_info_); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(response_info_); 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> request_headers = 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ToVector(request_info_->headers); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We examine the contents of request_info_ and response_info_ 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // mainly only in this test case. 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(GURL("ws://localhost/"), request_info_->url); 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(GURL("ws://localhost/"), response_info_->url); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(101, response_info_->status_code); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Switching Protocols", response_info_->status_text); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(12u, request_headers.size()); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Host", "localhost"), request_headers[0]); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]); 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Pragma", "no-cache"), request_headers[2]); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Cache-Control", "no-cache"), 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[3]); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[4]); 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Origin", "http://localhost"), 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[5]); 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"), 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[6]); 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[7]); 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip,deflate"), 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[8]); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"), 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[9]); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Sec-WebSocket-Key", request_headers[10].first); 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Extensions", 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits"), 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[11]); 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> response_headers = 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ToVector(*response_info_->headers); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(6u, response_headers.size()); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sort the headers for ease of verification. 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::sort(response_headers.begin(), response_headers.end()); 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]); 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]); 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]); 314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Confirm that the stream isn't established until the message loop runs. 317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { 318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check the path is used. 325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, PathIsUsed) { 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check that the origin is used. 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { 339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check that sub-protocols are sent and parsed. 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) { 352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string> sub_protocols; 353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n", 361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); 362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol()); 366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Unsolicited sub-protocols are rejected. 369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { 370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); 376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Response must not include 'Sec-WebSocket-Protocol' header " 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "if not present in request: chatv20.chromium.org", 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Missing sub-protocol response is rejected. 386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) { 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> sub_protocols; 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chat.example.com"); 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols, 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chat.example.com\r\n", 394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sent non-empty 'Sec-WebSocket-Protocol' header " 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "but no response was received", 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Only one sub-protocol can be accepted. 405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) { 406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string> sub_protocols; 407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n", 415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n"); 417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Protocol' header must not appear " 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "more than once in a response", 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Unmatched sub-protocol should be rejected. 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnmatchedSubProtocolInResponse) { 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> sub_protocols; 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols, 434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "chatv20.chromium.org\r\n", 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "in response does not match any of sent values", 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate extension basic success case. 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateSuccess) { 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("permessage-deflate"); 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate extensions success with all parameters. 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateParamsSuccess) { 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover; " 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "server_max_window_bits=11; client_max_window_bits=13; " 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "server_no_context_takeover"); 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify that incoming messages are actually decompressed with 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate enabled. 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse( 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/testing_path", 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/testing_path", 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStandardResponse( 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Extensions: permessage-deflate\r\n") + 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string( 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes) 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9)); 479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(stream_); 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<WebSocketFrame> frames; 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CompletionCallback callback; 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(OK, stream_->ReadFrames(&frames, callback)); 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(1U, frames.size()); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(5U, frames[0]->header.payload_length); 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Hello", std::string(frames[0]->data->data(), 5)); 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Unknown extension in the response is rejected 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, UnknownExtension) { 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("x-unknown-extension"); 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Found an unsupported extension 'x-unknown-extension' " 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "in 'Sec-WebSocket-Extensions' header", 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Malformed extensions are rejected (this file does not cover all possible 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// parse failures, as the parser is covered thoroughly by its own unit tests). 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MalformedExtension) { 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions(";"); 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Error during WebSocket handshake: 'Sec-WebSocket-Extensions' header " 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "value is rejected by the parser: ;", 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The permessage-deflate extension may only be specified once. 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, OnlyOnePerMessageDeflateAllowed) { 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate, permessage-deflate; client_max_window_bits=10"); 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: " 521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received duplicate permessage-deflate response", 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters may not be duplicated. 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, NoDuplicateParameters) { 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover; " 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "client_no_context_takeover"); 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received duplicate permessage-deflate extension parameter " 535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "client_no_context_takeover", 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters must start with "client_" or "server_" 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterPrefix) { 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; absurd_no_context_takeover"); 543a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received an unexpected permessage-deflate extension parameter", 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters must be either *_no_context_takeover or 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterSuffix) { 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_content_bits=5"); 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received an unexpected permessage-deflate extension parameter", 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_no_context_takeover parameters must not have an argument 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterValue) { 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover=true"); 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_no_context_takeover parameter", 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must have an argument 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, NoMaxWindowBitsArgument) { 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("permessage-deflate; client_max_window_bits"); 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 582a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 583a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "client_max_window_bits must have value", 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be an integer 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueInteger) { 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=banana"); 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 595a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be >= 8 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooSmall) { 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=7"); 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 606a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 607a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be <= 15 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooBig) { 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits=16"); 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_max_window_bits parameter", 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must not start with 0 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithZero) { 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits=08"); 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_max_window_bits parameter", 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must not start with + 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithPlus) { 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=+9"); 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 642a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 643a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(ricea): Check that WebSocketDeflateStream is initialised with the 6485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// arguments from the server. This is difficult because the data written to the 6495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// socket is randomly masked. 6505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Additional Sec-WebSocket-Accept headers should be rejected. 652a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, DoubleAccept) { 653a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 654a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "ws://localhost/", 655a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 659a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); 660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 661a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Accept' header must not appear " 6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "more than once in a response", 6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 667a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 668a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 669a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Response code 200 must be rejected. 670a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) { 671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kInvalidStatusCodeResponse[] = 672a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 200 OK\r\n" 673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 674a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 677a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 681a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 682a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kInvalidStatusCodeResponse); 683a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", 6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Redirects are not followed (according to the WHATWG WebSocket API, which 690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// overrides RFC6455 for browser applications). 691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, RedirectsRejected) { 692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kRedirectResponse[] = 693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 302 Moved Temporarily\r\n" 694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Content-Type: text/html\r\n" 695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Content-Length: 34\r\n" 696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: keep-alive\r\n" 697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Location: ws://localhost/other\r\n" 698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n" 699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "<title>Moved</title><h1>Moved</h1>"; 700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 703a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kRedirectResponse); 706a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", 7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 710a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 711a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Malformed responses should be rejected. HttpStreamParser will accept just 713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// about any garbage in the middle of the headers. To make it give up, the junk 714a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// has to be at the start of the response. Even then, it just gets treated as an 715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// HTTP/0.9 response. 716a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MalformedResponse) { 717a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMalformedResponse[] = 718a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "220 mx.google.com ESMTP\r\n" 719a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 OK\r\n" 720a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 721a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 725a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 726a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 727a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 728a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMalformedResponse); 730a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 732a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Invalid status line", 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 736a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Upgrade header must be present. 737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) { 738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingUpgradeResponse[] = 739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 740a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 741a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 746a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 747a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 748a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingUpgradeResponse); 749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 754a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 755a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// There must only be one upgrade header. 756a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { 757a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 758a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "ws://localhost/", 759a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 760a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 762a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", "Upgrade: HTTP/2.0\r\n"); 763a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Upgrade' header must not appear more than once in a response", 7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// There must only be one correct upgrade header. 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, IncorrectUpgradeHeader) { 7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kMissingUpgradeResponse[] = 7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: Upgrade\r\n" 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: hogefuga\r\n" 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 781a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMissingUpgradeResponse); 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Upgrade' header value is not 'WebSocket': hogefuga", 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 789a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 791a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connection header must be present. 792a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) { 793a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingConnectionResponse[] = 794a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 795a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 796a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 797a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 799a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 800a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 801a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 802a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 803a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingConnectionResponse); 804a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Connection' header is missing", 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Connection header must contain "Upgrade". 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, IncorrectConnectionHeader) { 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kMissingConnectionResponse[] = 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: websocket\r\n" 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: hogefuga\r\n" 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 822a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMissingConnectionResponse); 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Connection' header value must contain 'Upgrade'", 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connection header is permitted to contain other tokens. 833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) { 834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kAdditionalConnectionTokenResponse[] = 835a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 836a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 837a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade, Keep-Alive\r\n" 838a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 839a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 840a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 841a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 842a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kAdditionalConnectionTokenResponse); 846a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 848a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 849a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 850a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sec-WebSocket-Accept header must be present. 852a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) { 853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingAcceptResponse[] = 854a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 855a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 857a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 858a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 859a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 861a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 862a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 863a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingAcceptResponse); 864a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Accept' header is missing", 8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 869a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 870a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 871a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sec-WebSocket-Accept header must match the key that was sent. 872a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) { 873a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kIncorrectAcceptResponse[] = 874a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 875a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 876a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 877a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" 878a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 879a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 880a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 881a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 882a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 883a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 884a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kIncorrectAcceptResponse); 885a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Incorrect 'Sec-WebSocket-Accept' header value", 8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 890a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 891a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 892a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation works. 893a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, Cancellation) { 894a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 895a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 896a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 897a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 899a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 902a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connect failure must look just like negotiation failure. 905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { 906a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, NULL, 0)); 908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data( 909a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); 910a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 911a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", socket_data.Pass()); 912a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", 9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 918a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 919a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 920a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connect timeout must look just like any other failure. 921a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) { 922a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 923a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, NULL, 0)); 924a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data( 925a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); 926a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 927a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", socket_data.Pass()); 928a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 932a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 933a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 934a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during connect works. 935a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { 936a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 937a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, NULL, 0)); 938a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); 939a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 940a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 941a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 942a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data.Pass()); 943a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 944a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 946a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 947a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during write of the request headers works. 950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringWrite) { 951a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We seem to need at least two operations in order to use SetStop(). 952a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, 0, "GET / HTTP/"), 953a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite(ASYNC, 1, "1.1\r\n")}; 954a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We keep a copy of the pointer so that we can call RunFor() on it later. 955a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicSocketData* socket_data( 956a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, writes, arraysize(writes))); 957a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 958a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->SetStop(1); 959a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 960a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 961a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 962a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) make_scoped_ptr(socket_data)); 963a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->Run(); 964a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 965a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 967a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 970a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 971a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 972a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during read of the response headers works. 973a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { 974a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string request = WebSocketStandardRequest("/", "http://localhost", ""); 975a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; 976a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockRead reads[] = { 977a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), 978a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 979a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicSocketData* socket_data(new DeterministicSocketData( 980a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes))); 981a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 982a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->SetStop(1); 983a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 984a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 985a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 986a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) make_scoped_ptr(socket_data)); 987a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->Run(); 988a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 989a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Over-size response headers (> 256KB) should not cause a crash. This is a 9975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// regression test for crbug.com/339456. It is based on the layout test 9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// "cookie-flood.html". 9995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, VeryLargeResponseHeaders) { 10005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string set_cookie_headers; 10015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_cookie_headers.reserve(45 * 10000); 10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < 10000; ++i) { 10035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_cookie_headers += 10045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::StringPrintf("Set-Cookie: WK-websocket-test-flood-%d=1\r\n", i); 10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/", "/", NoSubProtocols(), 1007a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", "", set_cookie_headers); 10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If the remote host closes the connection without sending headers, we should 10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// log the console message "Connection closed before receiving a handshake 10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// response". 10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, NoResponse) { 1017a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string request = WebSocketStandardRequest("/", "http://localhost", ""); 10185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; 10195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockRead reads[] = {MockRead(ASYNC, 0, 1)}; 10205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeterministicSocketData* socket_data(new DeterministicSocketData( 10215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes))); 10225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 10235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 10245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 1025a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 10265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) make_scoped_ptr(socket_data)); 10275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) socket_data->RunFor(2); 10285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 1029a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 10305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 10315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Connection closed before receiving a handshake response", 10325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 1033a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1035c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketStreamCreateUMATest, Incomplete) { 1036c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string name("Net.WebSocket.HandshakeResult"); 1037c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> original(GetSamples(name)); 1038c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1039c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { 1040c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StreamCreation creation; 1041c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.CreateAndConnectStandard("ws://localhost/", 1042c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "/", 1043c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.NoSubProtocols(), 1044c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "http://localhost", 1045c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "", 1046c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ""); 1047c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1048c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1049c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); 1050c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_TRUE(samples); 1051c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (original) { 1052c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch samples->Subtract(*original); // Cancel the original values. 1053c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1054c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); 1055c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(CONNECTED)); 1056c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(FAILED)); 1057c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 1058c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1059c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketStreamCreateUMATest, Connected) { 1060c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string name("Net.WebSocket.HandshakeResult"); 1061c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> original(GetSamples(name)); 1062c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1063c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { 1064c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StreamCreation creation; 1065c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.CreateAndConnectStandard("ws://localhost/", 1066c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "/", 1067c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.NoSubProtocols(), 1068c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "http://localhost", 1069c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "", 1070c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ""); 1071c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.RunUntilIdle(); 1072c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1073c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1074c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); 1075c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_TRUE(samples); 1076c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (original) { 1077c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch samples->Subtract(*original); // Cancel the original values. 1078c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1079c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(INCOMPLETE)); 1080c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(1, samples->GetCount(CONNECTED)); 1081c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(FAILED)); 1082c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 1083c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1084c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketStreamCreateUMATest, Failed) { 1085c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string name("Net.WebSocket.HandshakeResult"); 1086c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> original(GetSamples(name)); 1087c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1088c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { 1089c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch StreamCreation creation; 1090c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch static const char kInvalidStatusCodeResponse[] = 1091c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "HTTP/1.1 200 OK\r\n" 1092c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "Upgrade: websocket\r\n" 1093c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "Connection: Upgrade\r\n" 1094c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 1095c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "\r\n"; 1096c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.CreateAndConnectCustomResponse("ws://localhost/", 1097c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "/", 1098c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.NoSubProtocols(), 1099c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "http://localhost", 1100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "", 1101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kInvalidStatusCodeResponse); 1102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch creation.RunUntilIdle(); 1103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_ptr<base::HistogramSamples> samples(GetSamples(name)); 1106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ASSERT_TRUE(samples); 1107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (original) { 1108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch samples->Subtract(*original); // Cancel the original values. 1109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(INCOMPLETE)); 1111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, samples->GetCount(CONNECTED)); 1112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(1, samples->GetCount(FAILED)); 1113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 1114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 1116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace net 1117