websocket_stream_test.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/net_errors.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_request_headers.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_response_headers.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/client_socket_handle.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/socket_test_util.h" 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_request_test_util.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_basic_handshake_stream.h" 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_frame.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_request_info.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_response_info.h" 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_handshake_stream_create_helper.h" 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_test_util.h" 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h" 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/origin.h" 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace net { 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef std::pair<std::string, std::string> HeaderKeyValuePair; 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::vector<HeaderKeyValuePair> ToVector(const HttpRequestHeaders& headers) { 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HttpRequestHeaders::Iterator it(headers); 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> result; 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (it.GetNext()) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.push_back(HeaderKeyValuePair(it.name(), it.value())); 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::vector<HeaderKeyValuePair> ToVector(const HttpResponseHeaders& headers) { 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void* iter = NULL; 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string name, value; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> result; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (headers.EnumerateHeaderLines(&iter, &name, &value)) 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.push_back(HeaderKeyValuePair(name, value)); 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// deterministic key to use in the WebSocket handshake. 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class DeterministicKeyWebSocketHandshakeStreamCreateHelper 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : public WebSocketHandshakeStreamCreateHelper { 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicKeyWebSocketHandshakeStreamCreateHelper( 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStream::ConnectDelegate* connect_delegate, 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& requested_subprotocols) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : WebSocketHandshakeStreamCreateHelper(connect_delegate, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) requested_subprotocols) {} 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual WebSocketHandshakeStreamBase* CreateBasicStream( 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<ClientSocketHandle> connection, 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool using_proxy) OVERRIDE { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketHandshakeStreamCreateHelper::CreateBasicStream(connection.Pass(), 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) using_proxy); 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // This will break in an obvious way if the type created by 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // CreateBasicStream() changes. 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<WebSocketBasicHandshakeStream*>(stream()) 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return stream(); 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class WebSocketStreamCreateTest : public ::testing::Test { 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected: 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStreamCreateTest(): has_failed_(false) {} 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectCustomResponse( 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_url, 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_path, 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_request_headers, 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& response_body) { 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.SetExpectations( 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStandardRequest(socket_path, origin, extra_request_headers), 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) response_body); 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStream(socket_url, sub_protocols, origin); 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // errors like "Unable to perform synchronous IO while stopped" will occur. 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectStandard(const std::string& socket_url, 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_path, 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_request_headers, 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_response_headers) { 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse( 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_url, 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_path, 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) origin, 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) extra_request_headers, 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStandardResponse(extra_response_headers)); 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectRawExpectations( 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_url, 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data) { 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.SetRawExpectations(socket_data.Pass()); 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStream(socket_url, sub_protocols, origin); 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // A wrapper for CreateAndConnectStreamForTesting that knows about our default 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // parameters. 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void CreateAndConnectStream(const std::string& socket_url, 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin) { 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate( 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new TestConnectDelegate(this)); 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStream::ConnectDelegate* delegate = connect_delegate.get(); 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_ = ::net::CreateAndConnectStreamForTesting( 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GURL(socket_url), 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeStreamCreateHelper>( 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicKeyWebSocketHandshakeStreamCreateHelper( 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate, sub_protocols)), 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url::Origin(origin), 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url_request_context_host_.GetURLRequestContext(), 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BoundNetLog(), 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_delegate.Pass()); 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // A simple function to make the tests more readable. Creates an empty vector. 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static std::vector<std::string> NoSubProtocols() { 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return std::vector<std::string>(); 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& failure_message() const { return failure_message_; } 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_failed() const { return has_failed_; } 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) class TestConnectDelegate : public WebSocketStream::ConnectDelegate { 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit TestConnectDelegate(WebSocketStreamCreateTest* owner) 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : owner_(owner) {} 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void OnSuccess(scoped_ptr<WebSocketStream> stream) OVERRIDE { 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream.swap(owner_->stream_); 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnFailure(const std::string& message) OVERRIDE { 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->has_failed_ = true; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->failure_message_ = message; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnStartOpeningHandshake( 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE { 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (owner_->request_info_) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ADD_FAILURE(); 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->request_info_ = request.Pass(); 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnFinishOpeningHandshake( 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE { 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (owner_->response_info_) 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ADD_FAILURE(); 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->response_info_ = response.Pass(); 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStreamCreateTest* owner_; 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketTestURLRequestContextHost url_request_context_host_; 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStreamRequest> stream_request_; 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only set if the connection succeeded. 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStream> stream_; 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only set if the connection failed. 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string failure_message_; 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool has_failed_; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request_info_; 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response_info_; 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// There are enough tests of the Sec-WebSocket-Extensions header that they 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// deserve their own test fixture. 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class WebSocketStreamCreateExtensionTest : public WebSocketStreamCreateTest { 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Performs a standard connect, with the value of the Sec-WebSocket-Extensions 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // header in the response set to |extensions_header_value|. Runs the event 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // loop to allow the connect to complete. 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void CreateAndConnectWithExtensions( 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extensions_header_value) { 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectStandard( 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/testing_path", 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/testing_path", 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Confirm that the basic case works as expected. 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(response_info_); 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, HandshakeInfo) { 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kResponse[] = 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: websocket\r\n" 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: Upgrade\r\n" 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "foo: bar, baz\r\n" 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "hoge: fuga\r\n" 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "hoge: piyo\r\n" 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse( 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/", 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kResponse); 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(request_info_); 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(response_info_); 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> request_headers = 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ToVector(request_info_->headers); 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We examine the contents of request_info_ and response_info_ 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // mainly only in this test case. 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(GURL("ws://localhost/"), request_info_->url); 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(GURL("ws://localhost/"), response_info_->url); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(101, response_info_->status_code); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Switching Protocols", response_info_->status_text); 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(12u, request_headers.size()); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Host", "localhost"), request_headers[0]); 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]); 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Pragma", "no-cache"), request_headers[2]); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Cache-Control", "no-cache"), 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[3]); 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[4]); 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Origin", "http://localhost"), 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[5]); 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"), 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[6]); 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[7]); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip,deflate"), 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[8]); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"), 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[9]); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Sec-WebSocket-Key", request_headers[10].first); 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Extensions", 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits"), 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers[11]); 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<HeaderKeyValuePair> response_headers = 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ToVector(*response_info_->headers); 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(6u, response_headers.size()); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sort the headers for ease of verification. 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::sort(response_headers.begin(), response_headers.end()); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]); 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]); 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]); 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]); 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Confirm that the stream isn't established until the message loop runs. 292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check the path is used. 300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, PathIsUsed) { 301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check that the origin is used. 313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { 314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Check that sub-protocols are sent and parsed. 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) { 327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string> sub_protocols; 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n", 336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); 337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol()); 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Unsolicited sub-protocols are rejected. 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Response must not include 'Sec-WebSocket-Protocol' header " 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "if not present in request: chatv20.chromium.org", 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Missing sub-protocol response is rejected. 361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) { 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> sub_protocols; 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chat.example.com"); 364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols, 367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chat.example.com\r\n", 369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ""); 370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sent non-empty 'Sec-WebSocket-Protocol' header " 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "but no response was received", 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Only one sub-protocol can be accepted. 380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) { 381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string> sub_protocols; 382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, 387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n", 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "chatv20.chromium.org\r\n"); 392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Protocol' header must not appear " 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "more than once in a response", 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Unmatched sub-protocol should be rejected. 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, UnmatchedSubProtocolInResponse) { 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<std::string> sub_protocols; 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chatv11.chromium.org"); 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols.push_back("chatv20.chromium.org"); 406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/testing_path", 407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/testing_path", 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sub_protocols, 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://google.com", 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv11.chromium.org, " 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "chatv20.chromium.org\r\n", 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' " 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "in response does not match any of sent values", 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate extension basic success case. 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateSuccess) { 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("permessage-deflate"); 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate extensions success with all parameters. 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateParamsSuccess) { 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover; " 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "server_max_window_bits=11; client_max_window_bits=13; " 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "server_no_context_takeover"); 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(stream_); 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify that incoming messages are actually decompressed with 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate enabled. 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse( 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ws://localhost/testing_path", 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/testing_path", 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStandardResponse( 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Extensions: permessage-deflate\r\n") + 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string( 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes) 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9)); 454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(stream_); 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<WebSocketFrame> frames; 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CompletionCallback callback; 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(OK, stream_->ReadFrames(&frames, callback)); 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(1U, frames.size()); 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(5U, frames[0]->header.payload_length); 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Hello", std::string(frames[0]->data->data(), 5)); 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Unknown extension in the response is rejected 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, UnknownExtension) { 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("x-unknown-extension"); 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Found an unsupported extension 'x-unknown-extension' " 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "in 'Sec-WebSocket-Extensions' header", 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Malformed extensions are rejected (this file does not cover all possible 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// parse failures, as the parser is covered thoroughly by its own unit tests). 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MalformedExtension) { 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions(";"); 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Error during WebSocket handshake: 'Sec-WebSocket-Extensions' header " 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "value is rejected by the parser: ;", 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The permessage-deflate extension may only be specified once. 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, OnlyOnePerMessageDeflateAllowed) { 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate, permessage-deflate; client_max_window_bits=10"); 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: " 496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received duplicate permessage-deflate response", 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters may not be duplicated. 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, NoDuplicateParameters) { 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover; " 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "client_no_context_takeover"); 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received duplicate permessage-deflate extension parameter " 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "client_no_context_takeover", 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters must start with "client_" or "server_" 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterPrefix) { 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; absurd_no_context_takeover"); 518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 522a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received an unexpected permessage-deflate extension parameter", 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// permessage-deflate parameters must be either *_no_context_takeover or 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterSuffix) { 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_content_bits=5"); 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 534a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received an unexpected permessage-deflate extension parameter", 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_no_context_takeover parameters must not have an argument 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, BadParameterValue) { 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_no_context_takeover=true"); 5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (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 invalid client_no_context_takeover parameter", 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must have an argument 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, NoMaxWindowBitsArgument) { 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions("permessage-deflate; client_max_window_bits"); 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "client_max_window_bits must have value", 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be an integer 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueInteger) { 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=banana"); 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be >= 8 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooSmall) { 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=7"); 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 581a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 582a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must be <= 15 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueTooBig) { 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits=16"); 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_max_window_bits parameter", 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must not start with 0 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithZero) { 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; client_max_window_bits=08"); 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 605a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 606a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid client_max_window_bits parameter", 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// *_max_window_bits must not start with + 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateExtensionTest, MaxWindowBitsValueStartsWithPlus) { 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectWithExtensions( 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "permessage-deflate; server_max_window_bits=+9"); 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ( 617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Error during WebSocket handshake: Error in permessage-deflate: " 618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received invalid server_max_window_bits parameter", 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(ricea): Check that WebSocketDeflateStream is initialised with the 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// arguments from the server. This is difficult because the data written to the 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// socket is randomly masked. 6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 626a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Additional Sec-WebSocket-Accept headers should be rejected. 627a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, DoubleAccept) { 628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 629a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "ws://localhost/", 630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 631a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 633a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 634a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); 635a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 636a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Accept' header must not appear " 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "more than once in a response", 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 642a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 643a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Response code 200 must be rejected. 645a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) { 646a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kInvalidStatusCodeResponse[] = 647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 200 OK\r\n" 648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 650a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 652a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 653a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 654a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 655a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 657a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kInvalidStatusCodeResponse); 658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 662a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 663a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 664a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Redirects are not followed (according to the WHATWG WebSocket API, which 665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// overrides RFC6455 for browser applications). 666a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, RedirectsRejected) { 667a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kRedirectResponse[] = 668a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 302 Moved Temporarily\r\n" 669a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Content-Type: text/html\r\n" 670a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Content-Length: 34\r\n" 671a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: keep-alive\r\n" 672a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Location: ws://localhost/other\r\n" 673a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n" 674a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "<title>Moved</title><h1>Moved</h1>"; 675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 677a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 678a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kRedirectResponse); 681a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 685a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 686a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Malformed responses should be rejected. HttpStreamParser will accept just 688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// about any garbage in the middle of the headers. To make it give up, the junk 689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// has to be at the start of the response. Even then, it just gets treated as an 690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// HTTP/0.9 response. 691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MalformedResponse) { 692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMalformedResponse[] = 693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "220 mx.google.com ESMTP\r\n" 694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 OK\r\n" 695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 702a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMalformedResponse); 705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 707a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: Invalid status line", 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 709a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 710a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 711a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Upgrade header must be present. 712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) { 713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingUpgradeResponse[] = 714a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 716a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 717a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 718a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 719a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 720a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingUpgradeResponse); 724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 728a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 730a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// There must only be one upgrade header. 731a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { 732a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 733a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "ws://localhost/", 734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 736a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 737a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", "Upgrade: HTTP/2.0\r\n"); 738a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Upgrade' header must not appear more than once in a response", 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// There must only be one correct upgrade header. 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, IncorrectUpgradeHeader) { 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kMissingUpgradeResponse[] = 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: Upgrade\r\n" 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: hogefuga\r\n" 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 756a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMissingUpgradeResponse); 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Upgrade' header value is not 'WebSocket': hogefuga", 7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 764a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 765a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 766a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connection header must be present. 767a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) { 768a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingConnectionResponse[] = 769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 770a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 771a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 772a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 773a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 774a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 775a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 777a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 778a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingConnectionResponse); 779a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Connection' header is missing", 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Connection header must contain "Upgrade". 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, IncorrectConnectionHeader) { 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char kMissingConnectionResponse[] = 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Upgrade: websocket\r\n" 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Connection: hogefuga\r\n" 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "\r\n"; 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "/", 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 797a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "", 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMissingConnectionResponse); 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Connection' header value must contain 'Upgrade'", 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 805a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 806a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 807a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connection header is permitted to contain other tokens. 808a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) { 809a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kAdditionalConnectionTokenResponse[] = 810a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 811a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 812a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade, Keep-Alive\r\n" 813a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" 814a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 815a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 816a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 817a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 818a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 819a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 820a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kAdditionalConnectionTokenResponse); 821a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 823a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream_); 824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 825a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 826a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sec-WebSocket-Accept header must be present. 827a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) { 828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kMissingAcceptResponse[] = 829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 835a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 836a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 837a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 838a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kMissingAcceptResponse); 839a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'Sec-WebSocket-Accept' header is missing", 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 844a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 845a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 846a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sec-WebSocket-Accept header must match the key that was sent. 847a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) { 848a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static const char kIncorrectAcceptResponse[] = 849a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "HTTP/1.1 101 Switching Protocols\r\n" 850a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Upgrade: websocket\r\n" 851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Connection: Upgrade\r\n" 852a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" 853a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "\r\n"; 854a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectCustomResponse("ws://localhost/", 855a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "/", 856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 857a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 858a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", 859a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kIncorrectAcceptResponse); 860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error during WebSocket handshake: " 8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Incorrect 'Sec-WebSocket-Accept' header value", 8645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 865a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 866a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 867a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation works. 868a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, Cancellation) { 869a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectStandard( 870a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "ws://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); 871a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 872a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 874a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 8755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 8765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 877a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 878a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 879a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connect failure must look just like negotiation failure. 880a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { 881a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 882a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, NULL, 0)); 883a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data( 884a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); 885a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 886a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", socket_data.Pass()); 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 8885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", 8905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(request_info_); 8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 893a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 894a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 895a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Connect timeout must look just like any other failure. 896a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) { 897a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 898a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, NULL, 0)); 899a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data( 900a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); 901a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), 902a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", socket_data.Pass()); 903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", 9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 909a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during connect works. 910a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { 911a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<DeterministicSocketData> socket_data( 912a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, NULL, 0)); 913a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); 914a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 915a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 916a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 917a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data.Pass()); 918a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 919a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 921a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 922a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 923a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 924a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during write of the request headers works. 925a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringWrite) { 926a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We seem to need at least two operations in order to use SetStop(). 927a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, 0, "GET / HTTP/"), 928a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite(ASYNC, 1, "1.1\r\n")}; 929a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // We keep a copy of the pointer so that we can call RunFor() on it later. 930a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicSocketData* socket_data( 931a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new DeterministicSocketData(NULL, 0, writes, arraysize(writes))); 932a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 933a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->SetStop(1); 934a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 935a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 936a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 937a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) make_scoped_ptr(socket_data)); 938a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->Run(); 939a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 940a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 942a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 945a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 946a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 947a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Cancellation during read of the response headers works. 948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { 949a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string request = WebSocketStandardRequest("/", "http://localhost", ""); 950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; 951a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockRead reads[] = { 952a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), 953a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 954a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicSocketData* socket_data(new DeterministicSocketData( 955a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes))); 956a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 957a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->SetStop(1); 958a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 959a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NoSubProtocols(), 960a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 961a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) make_scoped_ptr(socket_data)); 962a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_data->Run(); 963a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_request_.reset(); 964a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RunUntilIdle(); 9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(has_failed()); 9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(stream_); 9675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(request_info_); 9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Over-size response headers (> 256KB) should not cause a crash. This is a 9725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// regression test for crbug.com/339456. It is based on the layout test 9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// "cookie-flood.html". 9745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, VeryLargeResponseHeaders) { 9755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string set_cookie_headers; 9765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_cookie_headers.reserve(45 * 10000); 9775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < 10000; ++i) { 9785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_cookie_headers += 9795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::StringPrintf("Set-Cookie: WK-websocket-test-flood-%d=1\r\n", i); 9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectStandard("ws://localhost/", "/", NoSubProtocols(), 982a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", "", set_cookie_headers); 9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunUntilIdle(); 9845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 9855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If the remote host closes the connection without sending headers, we should 9895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// log the console message "Connection closed before receiving a handshake 9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// response". 9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketStreamCreateTest, NoResponse) { 992a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string request = WebSocketStandardRequest("/", "http://localhost", ""); 9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; 9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockRead reads[] = {MockRead(ASYNC, 0, 1)}; 9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeterministicSocketData* socket_data(new DeterministicSocketData( 9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reads, arraysize(reads), writes, arraysize(writes))); 9975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); 9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateAndConnectRawExpectations("ws://localhost/", 9995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NoSubProtocols(), 1000a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "http://localhost", 10015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) make_scoped_ptr(socket_data)); 10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) socket_data->RunFor(2); 10035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_TRUE(has_failed()); 1004a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream_); 10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(response_info_); 10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ("Connection closed before receiving a handshake response", 10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) failure_message()); 1008a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1009a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1010a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 1011a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace net 1012