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