1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_ 6 #define NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "base/macros.h" 16 #include "base/optional.h" 17 #include "net/http/http_basic_state.h" 18 #include "net/http/http_request_headers.h" 19 #include "net/http/http_stream_parser.h" 20 #include "net/socket/client_socket_handle.h" 21 #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h" 22 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" 23 #include "net/url_request/url_request_test_util.h" 24 #include "net/websockets/websocket_handshake_stream_create_helper.h" 25 #include "net/websockets/websocket_stream.h" 26 27 namespace url { 28 class Origin; 29 } // namespace url 30 31 namespace net { 32 33 using WebSocketExtraHeaders = std::vector<std::pair<std::string, std::string>>; 34 35 class MockClientSocketFactory; 36 class WebSocketBasicHandshakeStream; 37 class ProxyResolutionService; 38 class SequencedSocketData; 39 class IPEndPoint; 40 struct SSLSocketDataProvider; 41 42 class LinearCongruentialGenerator { 43 public: 44 explicit LinearCongruentialGenerator(uint32_t seed); 45 uint32_t Generate(); 46 47 private: 48 uint64_t current_; 49 }; 50 51 // Converts a vector of header key-value pairs into a single string. 52 std::string WebSocketExtraHeadersToString(const WebSocketExtraHeaders& headers); 53 54 // Converts a vector of header key-value pairs into an HttpRequestHeaders 55 HttpRequestHeaders WebSocketExtraHeadersToHttpRequestHeaders( 56 const WebSocketExtraHeaders& headers); 57 58 // Generates a standard WebSocket handshake request. The challenge key used is 59 // "dGhlIHNhbXBsZSBub25jZQ==". Each header in |extra_headers| must be terminated 60 // with "\r\n". 61 std::string WebSocketStandardRequest( 62 const std::string& path, 63 const std::string& host, 64 const url::Origin& origin, 65 const std::string& send_additional_request_headers, 66 const std::string& extra_headers); 67 68 // Generates a standard WebSocket handshake request. The challenge key used is 69 // "dGhlIHNhbXBsZSBub25jZQ==". |cookies| must be empty or terminated with 70 // "\r\n". Each header in |extra_headers| must be terminated with "\r\n". 71 std::string WebSocketStandardRequestWithCookies( 72 const std::string& path, 73 const std::string& host, 74 const url::Origin& origin, 75 const std::string& cookies, 76 const std::string& send_additional_request_headers, 77 const std::string& extra_headers); 78 79 // A response with the appropriate accept header to match the above 80 // challenge key. Each header in |extra_headers| must be terminated with 81 // "\r\n". 82 std::string WebSocketStandardResponse(const std::string& extra_headers); 83 84 // WebSocketCommonTestHeaders() generates a common set of request headers 85 // corresponding to WebSocketStandardRequest("/", "www.example.org", 86 // url::Origin::Create(GURL("http://origin.example.org")), "", "") 87 HttpRequestHeaders WebSocketCommonTestHeaders(); 88 89 // Generates a handshake request header block when using WebSockets over HTTP/2. 90 spdy::Http2HeaderBlock WebSocketHttp2Request( 91 const std::string& path, 92 const std::string& authority, 93 const std::string& origin, 94 const WebSocketExtraHeaders& extra_headers); 95 96 // Generates a handshake response header block when using WebSockets over 97 // HTTP/2. 98 spdy::Http2HeaderBlock WebSocketHttp2Response( 99 const WebSocketExtraHeaders& extra_headers); 100 101 // This class provides a convenient way to construct a MockClientSocketFactory 102 // for WebSocket tests. 103 class WebSocketMockClientSocketFactoryMaker { 104 public: 105 WebSocketMockClientSocketFactoryMaker(); 106 ~WebSocketMockClientSocketFactoryMaker(); 107 108 // Tell the factory to create a socket which expects |expect_written| to be 109 // written, and responds with |return_to_read|. The test will fail if the 110 // expected text is not written, or all the bytes are not read. This adds data 111 // for a new mock-socket using AddRawExpections(), and so can be called 112 // multiple times to queue up multiple mock sockets, but usually in those 113 // cases the lower-level AddRawExpections() interface is more appropriate. 114 void SetExpectations(const std::string& expect_written, 115 const std::string& return_to_read); 116 117 // A low-level interface to permit arbitrary expectations to be added. The 118 // mock sockets will be created in the same order that they were added. 119 void AddRawExpectations(std::unique_ptr<SequencedSocketData> socket_data); 120 121 // Allow an SSL socket data provider to be added. You must also supply a mock 122 // transport socket for it to use. If the mock SSL handshake fails then the 123 // mock transport socket will connect but have nothing read or written. If the 124 // mock handshake succeeds then the data from the underlying transport socket 125 // will be passed through unchanged (without encryption). 126 void AddSSLSocketDataProvider( 127 std::unique_ptr<SSLSocketDataProvider> ssl_socket_data); 128 129 // Call to get a pointer to the factory, which remains owned by this object. 130 MockClientSocketFactory* factory(); 131 132 private: 133 struct Detail; 134 std::unique_ptr<Detail> detail_; 135 136 DISALLOW_COPY_AND_ASSIGN(WebSocketMockClientSocketFactoryMaker); 137 }; 138 139 // This class encapsulates the details of creating a 140 // TestURLRequestContext that returns mock ClientSocketHandles that do what is 141 // required by the tests. 142 struct WebSocketTestURLRequestContextHost { 143 public: 144 WebSocketTestURLRequestContextHost(); 145 ~WebSocketTestURLRequestContextHost(); 146 SetExpectationsWebSocketTestURLRequestContextHost147 void SetExpectations(const std::string& expect_written, 148 const std::string& return_to_read) { 149 maker_.SetExpectations(expect_written, return_to_read); 150 } 151 152 void AddRawExpectations(std::unique_ptr<SequencedSocketData> socket_data); 153 154 // Allow an SSL socket data provider to be added. 155 void AddSSLSocketDataProvider( 156 std::unique_ptr<SSLSocketDataProvider> ssl_socket_data); 157 158 // Allow a proxy to be set. Usage: 159 // SetProxyConfig("proxy1:8000"); 160 // Any syntax accepted by net::ProxyConfig::ParseFromString() will work. 161 // Do not call after GetURLRequestContext() has been called. 162 void SetProxyConfig(const std::string& proxy_rules); 163 164 // Call after calling one of SetExpections() or AddRawExpectations(). The 165 // returned pointer remains owned by this object. 166 TestURLRequestContext* GetURLRequestContext(); 167 network_delegateWebSocketTestURLRequestContextHost168 const TestNetworkDelegate& network_delegate() const { 169 return network_delegate_; 170 } 171 172 private: 173 WebSocketMockClientSocketFactoryMaker maker_; 174 TestURLRequestContext url_request_context_; 175 TestNetworkDelegate network_delegate_; 176 std::unique_ptr<ProxyResolutionService> proxy_resolution_service_; 177 bool url_request_context_initialized_; 178 179 DISALLOW_COPY_AND_ASSIGN(WebSocketTestURLRequestContextHost); 180 }; 181 182 // WebSocketStream::ConnectDelegate implementation that does nothing. 183 class DummyConnectDelegate : public WebSocketStream::ConnectDelegate { 184 public: 185 DummyConnectDelegate() = default; 186 ~DummyConnectDelegate() override = default; OnCreateRequest(URLRequest * url_request)187 void OnCreateRequest(URLRequest* url_request) override {} OnSuccess(std::unique_ptr<WebSocketStream> stream,std::unique_ptr<WebSocketHandshakeResponseInfo> response)188 void OnSuccess( 189 std::unique_ptr<WebSocketStream> stream, 190 std::unique_ptr<WebSocketHandshakeResponseInfo> response) override {} OnFailure(const std::string & message,int net_error,base::Optional<int> response_code)191 void OnFailure(const std::string& message, 192 int net_error, 193 base::Optional<int> response_code) override {} OnStartOpeningHandshake(std::unique_ptr<WebSocketHandshakeRequestInfo> request)194 void OnStartOpeningHandshake( 195 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {} OnSSLCertificateError(std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> ssl_error_callbacks,int net_error,const SSLInfo & ssl_info,bool fatal)196 void OnSSLCertificateError( 197 std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> 198 ssl_error_callbacks, 199 int net_error, 200 const SSLInfo& ssl_info, 201 bool fatal) override {} 202 int OnAuthRequired(const AuthChallengeInfo& auth_info, 203 scoped_refptr<HttpResponseHeaders> response_headers, 204 const IPEndPoint& remote_endpoint, 205 base::OnceCallback<void(const AuthCredentials*)> callback, 206 base::Optional<AuthCredentials>* credentials) override; 207 }; 208 209 // WebSocketStreamRequestAPI implementation that sets the value of 210 // Sec-WebSocket-Key to the deterministic key that is used by tests. 211 class TestWebSocketStreamRequestAPI : public WebSocketStreamRequestAPI { 212 public: 213 TestWebSocketStreamRequestAPI() = default; 214 ~TestWebSocketStreamRequestAPI() override = default; 215 void OnBasicHandshakeStreamCreated( 216 WebSocketBasicHandshakeStream* handshake_stream) override; 217 void OnHttp2HandshakeStreamCreated( 218 WebSocketHttp2HandshakeStream* handshake_stream) override; OnFailure(const std::string & message,int net_error,base::Optional<int> response_code)219 void OnFailure(const std::string& message, 220 int net_error, 221 base::Optional<int> response_code) override {} 222 }; 223 224 // A sub-class of WebSocketHandshakeStreamCreateHelper which sets a 225 // deterministic key to use in the WebSocket handshake, and uses a dummy 226 // ConnectDelegate and WebSocketStreamRequestAPI. 227 class TestWebSocketHandshakeStreamCreateHelper 228 : public WebSocketHandshakeStreamCreateHelper { 229 public: 230 // Constructor for using dummy ConnectDelegate and WebSocketStreamRequestAPI. TestWebSocketHandshakeStreamCreateHelper()231 TestWebSocketHandshakeStreamCreateHelper() 232 : WebSocketHandshakeStreamCreateHelper(&connect_delegate_, 233 /* requested_subprotocols = */ {}, 234 &request_) {} 235 236 ~TestWebSocketHandshakeStreamCreateHelper() override = default; 237 238 private: 239 DummyConnectDelegate connect_delegate_; 240 TestWebSocketStreamRequestAPI request_; 241 242 DISALLOW_COPY_AND_ASSIGN(TestWebSocketHandshakeStreamCreateHelper); 243 }; 244 245 } // namespace net 246 247 #endif // NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_ 248