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_handshake_stream_create_helper.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/completion_callback.h" 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/net_errors.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_request_headers.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_request_info.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_response_headers.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_response_info.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/client_socket_handle.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/socket_test_util.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_basic_handshake_stream.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_stream.h" 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_test_util.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "url/gurl.h" 20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace net { 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace { 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This class encapsulates the details of creating a mock ClientSocketHandle. 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MockClientSocketHandleFactory { 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockClientSocketHandleFactory() 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : histograms_("a"), 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) pool_(1, 1, &histograms_, socket_factory_maker_.factory()) {} 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The created socket expects |expect_written| to be written to the socket, 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // and will respond with |return_to_read|. The test will fail if the expected 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // text is not written, or if all the bytes are not read. 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<ClientSocketHandle> CreateClientSocketHandle( 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& expect_written, 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& return_to_read) { 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_factory_maker_.SetExpectations(expect_written, return_to_read); 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle); 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_handle->Init( 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "a", 41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_refptr<MockTransportSocketParams>(), 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MEDIUM, 43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CompletionCallback(), 44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &pool_, 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) BoundNetLog()); 46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return socket_handle.Pass(); 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketDeterministicMockClientSocketFactoryMaker socket_factory_maker_; 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ClientSocketPoolHistograms histograms_; 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockTransportClientSocketPool pool_; 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockClientSocketHandleFactory); 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class WebSocketHandshakeStreamCreateHelperTest : public ::testing::Test { 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected: 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStream> CreateAndInitializeStream( 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_url, 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& socket_path, 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<std::string>& sub_protocols, 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& origin, 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_request_headers, 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& extra_response_headers) { 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketHandshakeStreamCreateHelper create_helper(sub_protocols); 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<ClientSocketHandle> socket_handle = 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_handle_factory_.CreateClientSocketHandle( 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStandardRequest( 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) socket_path, origin, extra_request_headers), 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) WebSocketStandardResponse(extra_response_headers)); 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeStreamBase> handshake( 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) create_helper.CreateBasicStream(socket_handle.Pass(), false)); 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If in future the implementation type returned by CreateBasicStream() 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // changes, this static_cast will be wrong. However, in that case the test 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // will fail and AddressSanitizer should identify the issue. 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static_cast<WebSocketBasicHandshakeStream*>(handshake.get()) 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ=="); 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HttpRequestInfo request_info; 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_info.url = GURL(socket_url); 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_info.method = "GET"; 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_info.load_flags = LOAD_DISABLE_CACHE | LOAD_DO_NOT_PROMPT_FOR_LOGIN; 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int rv = handshake->InitializeStream( 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &request_info, DEFAULT_PRIORITY, BoundNetLog(), CompletionCallback()); 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(OK, rv); 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HttpRequestHeaders headers; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("Host", "localhost"); 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("Connection", "Upgrade"); 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("Upgrade", "websocket"); 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("Origin", origin); 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("Sec-WebSocket-Version", "13"); 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("User-Agent", ""); 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("Accept-Encoding", "gzip,deflate"); 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetHeader("Accept-Language", "en-us,fr"); 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) HttpResponseInfo response; 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TestCompletionCallback dummy; 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rv = handshake->SendRequest(headers, &response, dummy.callback()); 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(OK, rv); 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) rv = handshake->ReadResponseHeaders(dummy.callback()); 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(OK, rv); 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(101, response.headers->response_code()); 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(response.headers->HasHeaderValue("Connection", "Upgrade")); 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(response.headers->HasHeaderValue("Upgrade", "websocket")); 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return handshake->Upgrade(); 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockClientSocketHandleFactory socket_handle_factory_; 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Confirm that the basic case works as expected. 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketHandshakeStreamCreateHelperTest, BasicStream) { 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStream> stream = 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndInitializeStream("ws://localhost/", "/", 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string>(), "http://localhost/", 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "", ""); 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ("", stream->GetExtensions()); 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ("", stream->GetSubProtocol()); 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Verify that the sub-protocols are passed through. 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WebSocketHandshakeStreamCreateHelperTest, SubProtocols) { 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::vector<std::string> sub_protocols; 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("chat"); 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols.push_back("superchat"); 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<WebSocketStream> stream = 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateAndInitializeStream("ws://localhost/", "/", 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sub_protocols, "http://localhost/", 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: chat, superchat\r\n", 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "Sec-WebSocket-Protocol: superchat\r\n"); 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ("superchat", stream->GetSubProtocol()); 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// TODO(ricea): Test extensions once they are implemented. 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace net 146