1 // Copyright 2014 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_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ 6 #define NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ 7 8 #include <stdint.h> 9 10 #include <optional> 11 #include <set> 12 #include <string> 13 #include <vector> 14 15 #include "base/compiler_specific.h" 16 #include "base/functional/callback.h" 17 #include "base/memory/raw_ptr.h" 18 #include "base/memory/scoped_refptr.h" 19 #include "base/memory/weak_ptr.h" 20 #include "base/time/time.h" 21 #include "net/base/completion_once_callback.h" 22 #include "net/base/io_buffer.h" 23 #include "net/base/load_flags.h" 24 #include "net/base/net_error_details.h" 25 #include "net/base/net_errors.h" 26 #include "net/base/request_priority.h" 27 #include "net/base/test_completion_callback.h" 28 #include "net/base/transport_info.h" 29 #include "net/cert/x509_certificate.h" 30 #include "net/disk_cache/disk_cache.h" 31 #include "net/http/http_cache.h" 32 #include "net/http/http_request_info.h" 33 #include "net/http/http_response_headers.h" 34 #include "net/http/http_response_info.h" 35 #include "net/http/http_transaction.h" 36 #include "net/log/net_log_source.h" 37 #include "net/socket/connection_attempts.h" 38 39 namespace net { 40 41 class IOBuffer; 42 class SSLPrivateKey; 43 class NetLogWithSource; 44 struct HttpRequestInfo; 45 46 //----------------------------------------------------------------------------- 47 // mock transaction data 48 49 // these flags may be combined to form the test_mode field 50 enum { 51 TEST_MODE_NORMAL = 0, 52 TEST_MODE_SYNC_NET_START = 1 << 0, 53 TEST_MODE_SYNC_NET_READ = 1 << 1, 54 TEST_MODE_SYNC_CACHE_START = 1 << 2, 55 TEST_MODE_SYNC_CACHE_READ = 1 << 3, 56 TEST_MODE_SYNC_CACHE_WRITE = 1 << 4, 57 TEST_MODE_SYNC_ALL = (TEST_MODE_SYNC_NET_START | TEST_MODE_SYNC_NET_READ | 58 TEST_MODE_SYNC_CACHE_START | TEST_MODE_SYNC_CACHE_READ | 59 TEST_MODE_SYNC_CACHE_WRITE), 60 TEST_MODE_SLOW_READ = 1 << 5 61 }; 62 63 using MockTransactionReadHandler = base::RepeatingCallback< 64 int(int64_t content_length, int64_t offset, IOBuffer* buf, int buf_len)>; 65 66 using MockTransactionHandler = 67 base::RepeatingCallback<void(const HttpRequestInfo* request, 68 std::string* response_status, 69 std::string* response_headers, 70 std::string* response_data)>; 71 72 // Default TransportInfo suitable for most MockTransactions. 73 // Describes a direct connection to (127.0.0.1, 80). 74 TransportInfo DefaultTransportInfo(); 75 76 struct MockTransaction { 77 const char* url; 78 const char* method; 79 // If |request_time| is unspecified, the current time will be used. 80 base::Time request_time; 81 const char* request_headers; 82 int load_flags; 83 // Connection info passed to ConnectedCallback(), if any. 84 TransportInfo transport_info = DefaultTransportInfo(); 85 const char* status; 86 const char* response_headers; 87 // If |response_time| is unspecified, the current time will be used. 88 base::Time response_time; 89 const char* data; 90 // Any aliases for the requested URL, as read from DNS records. Includes all 91 // known aliases, e.g. from A, AAAA, or HTTPS, not just from the address used 92 // for the connection, in no particular order. 93 std::set<std::string> dns_aliases; 94 std::optional<int64_t> fps_cache_filter; 95 std::optional<int64_t> browser_run_id; 96 int test_mode; 97 MockTransactionHandler handler; 98 MockTransactionReadHandler read_handler; 99 scoped_refptr<X509Certificate> cert; 100 CertStatus cert_status; 101 int ssl_connection_status; 102 // Value returned by MockNetworkTransaction::Start (potentially 103 // asynchronously if |!(test_mode & TEST_MODE_SYNC_NET_START)|.) 104 Error start_return_code; 105 // Value returned by MockNetworkTransaction::Read (potentially 106 // asynchronously if |!(test_mode & TEST_MODE_SYNC_NET_START)|.) 107 Error read_return_code; 108 }; 109 110 extern const MockTransaction kSimpleGET_Transaction; 111 extern const MockTransaction kSimplePOST_Transaction; 112 extern const MockTransaction kTypicalGET_Transaction; 113 extern const MockTransaction kETagGET_Transaction; 114 extern const MockTransaction kRangeGET_Transaction; 115 116 // returns the mock transaction for the given URL 117 const MockTransaction* FindMockTransaction(const GURL& url); 118 119 // Register a mock transaction that can be accessed via 120 // FindMockTransaction. There can be only one MockTransaction associated 121 // with a given URL. 122 struct ScopedMockTransaction : MockTransaction { 123 explicit ScopedMockTransaction(const char* url); 124 explicit ScopedMockTransaction(const MockTransaction& t, 125 const char* url = nullptr); 126 ~ScopedMockTransaction(); 127 }; 128 129 //----------------------------------------------------------------------------- 130 // mock http request 131 132 class MockHttpRequest : public HttpRequestInfo { 133 public: 134 explicit MockHttpRequest(const MockTransaction& t); 135 std::string CacheKey(); 136 }; 137 138 //----------------------------------------------------------------------------- 139 // use this class to test completely consuming a transaction 140 141 class TestTransactionConsumer { 142 public: 143 TestTransactionConsumer(RequestPriority priority, 144 HttpTransactionFactory* factory); 145 virtual ~TestTransactionConsumer(); 146 147 void Start(const HttpRequestInfo* request, const NetLogWithSource& net_log); 148 is_done()149 bool is_done() const { return state_ == State::kDone; } error()150 int error() const { return error_; } 151 response_info()152 const HttpResponseInfo* response_info() const { 153 return trans_->GetResponseInfo(); 154 } transaction()155 const HttpTransaction* transaction() const { return trans_.get(); } content()156 const std::string& content() const { return content_; } 157 158 private: 159 enum class State { kIdle, kStarting, kReading, kDone }; 160 161 void DidStart(int result); 162 void DidRead(int result); 163 void DidFinish(int result); 164 void Read(); 165 166 void OnIOComplete(int result); 167 168 State state_ = State::kIdle; 169 std::unique_ptr<HttpTransaction> trans_; 170 std::string content_; 171 scoped_refptr<IOBuffer> read_buf_; 172 int error_ = OK; 173 base::OnceClosure quit_closure_; 174 }; 175 176 //----------------------------------------------------------------------------- 177 // mock network layer 178 179 class MockNetworkLayer; 180 181 // This transaction class inspects the available set of mock transactions to 182 // find data for the request URL. It supports IO operations that complete 183 // synchronously or asynchronously to help exercise different code paths in the 184 // HttpCache implementation. 185 class MockNetworkTransaction final : public HttpTransaction { 186 typedef WebSocketHandshakeStreamBase::CreateHelper CreateHelper; 187 188 public: 189 MockNetworkTransaction(RequestPriority priority, MockNetworkLayer* factory); 190 ~MockNetworkTransaction() override; 191 192 int Start(const HttpRequestInfo* request, 193 CompletionOnceCallback callback, 194 const NetLogWithSource& net_log) override; 195 196 int RestartIgnoringLastError(CompletionOnceCallback callback) override; 197 198 int RestartWithCertificate(scoped_refptr<X509Certificate> client_cert, 199 scoped_refptr<SSLPrivateKey> client_private_key, 200 CompletionOnceCallback callback) override; 201 202 int RestartWithAuth(const AuthCredentials& credentials, 203 CompletionOnceCallback callback) override; 204 205 bool IsReadyToRestartForAuth() override; 206 207 int Read(IOBuffer* buf, 208 int buf_len, 209 CompletionOnceCallback callback) override; 210 void PopulateNetErrorDetails(NetErrorDetails* details) const override; 211 212 void StopCaching() override; 213 214 int64_t GetTotalReceivedBytes() const override; 215 216 int64_t GetTotalSentBytes() const override; 217 218 int64_t GetReceivedBodyBytes() const override; 219 220 void DoneReading() override; 221 222 const HttpResponseInfo* GetResponseInfo() const override; 223 224 LoadState GetLoadState() const override; 225 226 void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; 227 228 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; 229 230 bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; 231 232 void SetPriority(RequestPriority priority) override; 233 234 void SetWebSocketHandshakeStreamCreateHelper( 235 CreateHelper* create_helper) override; 236 237 void SetBeforeNetworkStartCallback( 238 BeforeNetworkStartCallback callback) override; 239 240 void SetConnectedCallback(const ConnectedCallback& callback) override; 241 SetRequestHeadersCallback(RequestHeadersCallback callback)242 void SetRequestHeadersCallback(RequestHeadersCallback callback) override {} SetResponseHeadersCallback(ResponseHeadersCallback)243 void SetResponseHeadersCallback(ResponseHeadersCallback) override {} SetEarlyResponseHeadersCallback(ResponseHeadersCallback)244 void SetEarlyResponseHeadersCallback(ResponseHeadersCallback) override {} 245 246 void SetModifyRequestHeadersCallback( 247 base::RepeatingCallback<void(HttpRequestHeaders*)> callback) override; 248 SetIsSharedDictionaryReadAllowedCallback(base::RepeatingCallback<bool ()> callback)249 void SetIsSharedDictionaryReadAllowedCallback( 250 base::RepeatingCallback<bool()> callback) override {} 251 252 int ResumeNetworkStart() override; 253 254 ConnectionAttempts GetConnectionAttempts() const override; 255 256 void CloseConnectionOnDestruction() override; 257 bool IsMdlMatchForMetrics() const override; 258 websocket_handshake_stream_create_helper()259 CreateHelper* websocket_handshake_stream_create_helper() { 260 return websocket_handshake_stream_create_helper_; 261 } 262 priority()263 RequestPriority priority() const { return priority_; } 264 AsWeakPtr()265 base::WeakPtr<MockNetworkTransaction> AsWeakPtr() { 266 return weak_factory_.GetWeakPtr(); 267 } 268 269 // Bogus value that will be returned by GetTotalReceivedBytes() if the 270 // MockNetworkTransaction was started. 271 static const int64_t kTotalReceivedBytes; 272 // Bogus value that will be returned by GetTotalSentBytes() if the 273 // MockNetworkTransaction was started. 274 static const int64_t kTotalSentBytes; 275 // Bogus value that will be returned by GetReceivedBodyBytes() if the 276 // MockNetworkTransaction was started. 277 static const int64_t kReceivedBodyBytes; 278 279 private: 280 enum class State { 281 NOTIFY_BEFORE_CREATE_STREAM, 282 CREATE_STREAM, 283 CREATE_STREAM_COMPLETE, 284 CONNECTED_CALLBACK, 285 CONNECTED_CALLBACK_COMPLETE, 286 BUILD_REQUEST, 287 BUILD_REQUEST_COMPLETE, 288 SEND_REQUEST, 289 SEND_REQUEST_COMPLETE, 290 READ_HEADERS, 291 READ_HEADERS_COMPLETE, 292 NONE 293 }; 294 295 int StartInternal(HttpRequestInfo request, CompletionOnceCallback callback); 296 int DoNotifyBeforeCreateStream(); 297 int DoCreateStream(); 298 int DoCreateStreamComplete(int result); 299 int DoConnectedCallback(); 300 int DoConnectedCallbackComplete(int result); 301 int DoBuildRequest(); 302 int DoBuildRequestComplete(int result); 303 int DoSendRequest(); 304 int DoSendRequestComplete(int result); 305 int DoReadHeaders(); 306 int DoReadHeadersComplete(int result); 307 308 // Runs the state transition loop. 309 int DoLoop(int result); 310 311 void OnIOComplete(int result); 312 313 void CallbackLater(CompletionOnceCallback callback, int result); 314 void RunCallback(CompletionOnceCallback callback, int result); 315 316 raw_ptr<const HttpRequestInfo> original_request_ptr_ = nullptr; 317 HttpRequestInfo current_request_; 318 State next_state_ = State::NONE; 319 NetLogWithSource net_log_; 320 321 CompletionOnceCallback callback_; 322 323 HttpResponseInfo response_; 324 std::string data_; 325 int64_t data_cursor_ = 0; 326 int64_t content_length_ = 0; 327 int test_mode_; 328 RequestPriority priority_; 329 raw_ptr<CreateHelper> websocket_handshake_stream_create_helper_ = nullptr; 330 BeforeNetworkStartCallback before_network_start_callback_; 331 ConnectedCallback connected_callback_; 332 base::WeakPtr<MockNetworkLayer> transaction_factory_; 333 int64_t received_bytes_ = 0; 334 int64_t sent_bytes_ = 0; 335 int64_t received_body_bytes_ = 0; 336 337 // NetLog ID of the fake / non-existent underlying socket used by the 338 // connection. Requires Start() be passed a NetLogWithSource with a real 339 // NetLog to 340 // be initialized. 341 unsigned int socket_log_id_ = NetLogSource::kInvalidId; 342 343 bool done_reading_called_ = false; 344 bool reading_ = false; 345 346 CompletionOnceCallback resume_start_callback_; // used for pause and restart. 347 348 base::RepeatingCallback<void(HttpRequestHeaders*)> 349 modify_request_headers_callback_; 350 351 base::WeakPtrFactory<MockNetworkTransaction> weak_factory_{this}; 352 }; 353 354 class MockNetworkLayer final : public HttpTransactionFactory { 355 public: 356 MockNetworkLayer(); 357 ~MockNetworkLayer() override; 358 transaction_count()359 int transaction_count() const { return transaction_count_; } done_reading_called()360 bool done_reading_called() const { return done_reading_called_; } stop_caching_called()361 bool stop_caching_called() const { return stop_caching_called_; } 362 void TransactionDoneReading(); 363 void TransactionStopCaching(); 364 365 // Resets the transaction count. Can be called after test setup in order to 366 // make test expectations independent of how test setup is performed. 367 void ResetTransactionCount(); 368 369 // Returns the last priority passed to CreateTransaction, or 370 // DEFAULT_PRIORITY if it hasn't been called yet. last_create_transaction_priority()371 RequestPriority last_create_transaction_priority() const { 372 return last_create_transaction_priority_; 373 } 374 375 // Returns the last transaction created by 376 // CreateTransaction. Returns a NULL WeakPtr if one has not been 377 // created yet, or the last transaction has been destroyed, or 378 // ClearLastTransaction() has been called and a new transaction 379 // hasn't been created yet. last_transaction()380 base::WeakPtr<MockNetworkTransaction> last_transaction() { 381 return last_transaction_; 382 } 383 384 // Makes last_transaction() return NULL until the next transaction 385 // is created. ClearLastTransaction()386 void ClearLastTransaction() { 387 last_transaction_.reset(); 388 } 389 390 // HttpTransactionFactory: 391 int CreateTransaction(RequestPriority priority, 392 std::unique_ptr<HttpTransaction>* trans) override; 393 HttpCache* GetCache() override; 394 HttpNetworkSession* GetSession() override; 395 396 // The caller must guarantee that |clock| will outlive this object. 397 void SetClock(base::Clock* clock); clock()398 base::Clock* clock() const { return clock_; } 399 400 // The current time (will use clock_ if it is non NULL). 401 base::Time Now(); 402 AsWeakPtr()403 base::WeakPtr<MockNetworkLayer> AsWeakPtr() { 404 return weak_factory_.GetWeakPtr(); 405 } 406 407 private: 408 int transaction_count_ = 0; 409 bool done_reading_called_ = false; 410 bool stop_caching_called_ = false; 411 RequestPriority last_create_transaction_priority_ = DEFAULT_PRIORITY; 412 413 // By default clock_ is NULL but it can be set to a custom clock by test 414 // frameworks using SetClock. 415 raw_ptr<base::Clock> clock_ = nullptr; 416 417 base::WeakPtr<MockNetworkTransaction> last_transaction_; 418 419 base::WeakPtrFactory<MockNetworkLayer> weak_factory_{this}; 420 }; 421 422 //----------------------------------------------------------------------------- 423 // helpers 424 425 // read the transaction completely 426 int ReadTransaction(HttpTransaction* trans, std::string* result); 427 428 //----------------------------------------------------------------------------- 429 // connected callback handler 430 431 // Used for injecting ConnectedCallback instances in HttpTransaction. 432 class ConnectedHandler { 433 public: 434 ConnectedHandler(); 435 ~ConnectedHandler(); 436 437 // Instances of this class are copyable and efficiently movable. 438 // WARNING: Do not move an instance to which a callback is bound. 439 ConnectedHandler(const ConnectedHandler&); 440 ConnectedHandler& operator=(const ConnectedHandler&); 441 ConnectedHandler(ConnectedHandler&&); 442 ConnectedHandler& operator=(ConnectedHandler&&); 443 444 // Returns a callback bound to this->OnConnected(). 445 // The returned callback must not outlive this instance. Callback()446 HttpTransaction::ConnectedCallback Callback() { 447 return base::BindRepeating(&ConnectedHandler::OnConnected, 448 base::Unretained(this)); 449 } 450 451 // Compatible with HttpTransaction::ConnectedCallback. 452 // Returns the last value passed to set_result(), if any, OK otherwise. 453 int OnConnected(const TransportInfo& info, CompletionOnceCallback callback); 454 455 // Returns the list of arguments with which OnConnected() was called. 456 // The arguments are listed in the same order as the calls were received. transports()457 const std::vector<TransportInfo>& transports() const { return transports_; } 458 459 // Sets the value to be returned by subsequent calls to OnConnected(). set_result(int result)460 void set_result(int result) { result_ = result; } 461 462 // If true, runs the callback supplied to OnConnected asynchronously with 463 // `result_`. Otherwise, the callback is skipped and `result_` is returned 464 // directly. set_run_callback(bool run_callback)465 void set_run_callback(bool run_callback) { run_callback_ = run_callback; } 466 467 private: 468 std::vector<TransportInfo> transports_; 469 int result_ = OK; 470 bool run_callback_ = false; 471 }; 472 473 } // namespace net 474 475 #endif // NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ 476