Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 1 | // Copyright 2014 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_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ |
| 6 | #define NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ |
| 7 | |
| 8 | #include "net/http/http_transaction.h" |
| 9 | |
| 10 | #include <string> |
| 11 | |
| 12 | #include "base/callback.h" |
| 13 | #include "base/compiler_specific.h" |
| 14 | #include "base/memory/weak_ptr.h" |
| 15 | #include "base/strings/string16.h" |
| 16 | #include "net/base/completion_once_callback.h" |
| 17 | #include "net/base/io_buffer.h" |
| 18 | #include "net/base/load_flags.h" |
| 19 | #include "net/base/net_error_details.h" |
| 20 | #include "net/base/net_errors.h" |
| 21 | #include "net/base/request_priority.h" |
| 22 | #include "net/base/test_completion_callback.h" |
| 23 | #include "net/disk_cache/disk_cache.h" |
| 24 | #include "net/http/http_cache.h" |
| 25 | #include "net/http/http_request_info.h" |
| 26 | #include "net/http/http_response_headers.h" |
| 27 | #include "net/http/http_response_info.h" |
| 28 | #include "net/socket/connection_attempts.h" |
| 29 | #include "starboard/types.h" |
| 30 | |
| 31 | namespace net { |
| 32 | |
| 33 | class HttpRequestHeaders; |
| 34 | class IOBuffer; |
| 35 | class SSLPrivateKey; |
| 36 | class X509Certificate; |
| 37 | class NetLogWithSource; |
| 38 | struct HttpRequestInfo; |
| 39 | |
| 40 | //----------------------------------------------------------------------------- |
| 41 | // mock transaction data |
| 42 | |
| 43 | // these flags may be combined to form the test_mode field |
| 44 | enum { |
| 45 | TEST_MODE_NORMAL = 0, |
| 46 | TEST_MODE_SYNC_NET_START = 1 << 0, |
| 47 | TEST_MODE_SYNC_NET_READ = 1 << 1, |
| 48 | TEST_MODE_SYNC_CACHE_START = 1 << 2, |
| 49 | TEST_MODE_SYNC_CACHE_READ = 1 << 3, |
| 50 | TEST_MODE_SYNC_CACHE_WRITE = 1 << 4, |
| 51 | TEST_MODE_SYNC_ALL = (TEST_MODE_SYNC_NET_START | TEST_MODE_SYNC_NET_READ | |
| 52 | TEST_MODE_SYNC_CACHE_START | TEST_MODE_SYNC_CACHE_READ | |
| 53 | TEST_MODE_SYNC_CACHE_WRITE), |
| 54 | TEST_MODE_SLOW_READ = 1 << 5 |
| 55 | }; |
| 56 | |
| 57 | using MockTransactionReadHandler = int (*)(int64_t content_length, |
| 58 | int64_t offset, |
| 59 | IOBuffer* buf, |
| 60 | int buf_len); |
| 61 | using MockTransactionHandler = void (*)(const HttpRequestInfo* request, |
| 62 | std::string* response_status, |
| 63 | std::string* response_headers, |
| 64 | std::string* response_data); |
| 65 | |
| 66 | struct MockTransaction { |
| 67 | const char* url; |
| 68 | const char* method; |
| 69 | // If |request_time| is unspecified, the current time will be used. |
| 70 | base::Time request_time; |
| 71 | const char* request_headers; |
| 72 | int load_flags; |
| 73 | const char* status; |
| 74 | const char* response_headers; |
| 75 | // If |response_time| is unspecified, the current time will be used. |
| 76 | base::Time response_time; |
| 77 | const char* data; |
| 78 | int test_mode; |
| 79 | MockTransactionHandler handler; |
| 80 | MockTransactionReadHandler read_handler; |
| 81 | scoped_refptr<X509Certificate> cert; |
| 82 | CertStatus cert_status; |
| 83 | int ssl_connection_status; |
| 84 | // Value returned by MockNetworkTransaction::Start (potentially |
| 85 | // asynchronously if |!(test_mode & TEST_MODE_SYNC_NET_START)|.) |
| 86 | Error start_return_code; |
| 87 | // Value returned by MockNetworkTransaction::Read (potentially |
| 88 | // asynchronously if |!(test_mode & TEST_MODE_SYNC_NET_START)|.) |
| 89 | Error read_return_code; |
| 90 | }; |
| 91 | |
| 92 | extern const MockTransaction kSimpleGET_Transaction; |
| 93 | extern const MockTransaction kSimplePOST_Transaction; |
| 94 | extern const MockTransaction kTypicalGET_Transaction; |
| 95 | extern const MockTransaction kETagGET_Transaction; |
| 96 | extern const MockTransaction kRangeGET_Transaction; |
| 97 | |
| 98 | // returns the mock transaction for the given URL |
| 99 | const MockTransaction* FindMockTransaction(const GURL& url); |
| 100 | |
| 101 | // Add/Remove a mock transaction that can be accessed via FindMockTransaction. |
| 102 | // There can be only one MockTransaction associated with a given URL. |
| 103 | void AddMockTransaction(const MockTransaction* trans); |
| 104 | void RemoveMockTransaction(const MockTransaction* trans); |
| 105 | |
| 106 | struct ScopedMockTransaction : MockTransaction { |
| 107 | ScopedMockTransaction() { |
| 108 | AddMockTransaction(this); |
| 109 | } |
| 110 | explicit ScopedMockTransaction(const MockTransaction& t) |
| 111 | : MockTransaction(t) { |
| 112 | AddMockTransaction(this); |
| 113 | } |
| 114 | ~ScopedMockTransaction() { |
| 115 | RemoveMockTransaction(this); |
| 116 | } |
| 117 | }; |
| 118 | |
| 119 | //----------------------------------------------------------------------------- |
| 120 | // mock http request |
| 121 | |
| 122 | class MockHttpRequest : public HttpRequestInfo { |
| 123 | public: |
| 124 | explicit MockHttpRequest(const MockTransaction& t); |
| 125 | }; |
| 126 | |
| 127 | //----------------------------------------------------------------------------- |
| 128 | // use this class to test completely consuming a transaction |
| 129 | |
| 130 | class TestTransactionConsumer { |
| 131 | public: |
| 132 | TestTransactionConsumer(RequestPriority priority, |
| 133 | HttpTransactionFactory* factory); |
| 134 | virtual ~TestTransactionConsumer(); |
| 135 | |
| 136 | void Start(const HttpRequestInfo* request, const NetLogWithSource& net_log); |
| 137 | |
| 138 | bool is_done() const { return state_ == DONE; } |
| 139 | int error() const { return error_; } |
| 140 | |
| 141 | const HttpResponseInfo* response_info() const { |
| 142 | return trans_->GetResponseInfo(); |
| 143 | } |
| 144 | const HttpTransaction* transaction() const { return trans_.get(); } |
| 145 | const std::string& content() const { return content_; } |
| 146 | |
| 147 | private: |
| 148 | enum State { |
| 149 | IDLE, |
| 150 | STARTING, |
| 151 | READING, |
| 152 | DONE |
| 153 | }; |
| 154 | |
| 155 | void DidStart(int result); |
| 156 | void DidRead(int result); |
| 157 | void DidFinish(int result); |
| 158 | void Read(); |
| 159 | |
| 160 | void OnIOComplete(int result); |
| 161 | |
| 162 | State state_; |
| 163 | std::unique_ptr<HttpTransaction> trans_; |
| 164 | std::string content_; |
| 165 | scoped_refptr<IOBuffer> read_buf_; |
| 166 | int error_; |
| 167 | |
| 168 | static int quit_counter_; |
| 169 | }; |
| 170 | |
| 171 | //----------------------------------------------------------------------------- |
| 172 | // mock network layer |
| 173 | |
| 174 | class MockNetworkLayer; |
| 175 | |
| 176 | // This transaction class inspects the available set of mock transactions to |
| 177 | // find data for the request URL. It supports IO operations that complete |
| 178 | // synchronously or asynchronously to help exercise different code paths in the |
| 179 | // HttpCache implementation. |
| 180 | class MockNetworkTransaction |
| 181 | : public HttpTransaction, |
| 182 | public base::SupportsWeakPtr<MockNetworkTransaction> { |
| 183 | typedef WebSocketHandshakeStreamBase::CreateHelper CreateHelper; |
| 184 | |
| 185 | public: |
| 186 | MockNetworkTransaction(RequestPriority priority, MockNetworkLayer* factory); |
| 187 | ~MockNetworkTransaction() override; |
| 188 | |
| 189 | int Start(const HttpRequestInfo* request, |
| 190 | CompletionOnceCallback callback, |
| 191 | const NetLogWithSource& net_log) override; |
| 192 | |
| 193 | int RestartIgnoringLastError(CompletionOnceCallback callback) override; |
| 194 | |
| 195 | int RestartWithCertificate(scoped_refptr<X509Certificate> client_cert, |
| 196 | scoped_refptr<SSLPrivateKey> client_private_key, |
| 197 | CompletionOnceCallback callback) override; |
| 198 | |
| 199 | int RestartWithAuth(const AuthCredentials& credentials, |
| 200 | CompletionOnceCallback callback) override; |
| 201 | |
| 202 | bool IsReadyToRestartForAuth() override; |
| 203 | |
| 204 | int Read(IOBuffer* buf, |
| 205 | int buf_len, |
| 206 | CompletionOnceCallback callback) override; |
| 207 | void PopulateNetErrorDetails(NetErrorDetails* details) const override; |
| 208 | |
| 209 | void StopCaching() override; |
| 210 | |
| 211 | bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; |
| 212 | |
| 213 | int64_t GetTotalReceivedBytes() const override; |
| 214 | |
| 215 | int64_t GetTotalSentBytes() const override; |
| 216 | |
| 217 | void DoneReading() override; |
| 218 | |
| 219 | const HttpResponseInfo* GetResponseInfo() const override; |
| 220 | |
| 221 | LoadState GetLoadState() const override; |
| 222 | |
| 223 | void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; |
| 224 | |
| 225 | bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; |
| 226 | |
| 227 | bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; |
| 228 | |
| 229 | void SetPriority(RequestPriority priority) override; |
| 230 | |
| 231 | void SetWebSocketHandshakeStreamCreateHelper( |
| 232 | CreateHelper* create_helper) override; |
| 233 | |
| 234 | void SetBeforeNetworkStartCallback( |
| 235 | const BeforeNetworkStartCallback& callback) override; |
| 236 | |
| 237 | void SetBeforeHeadersSentCallback( |
| 238 | const BeforeHeadersSentCallback& callback) override; |
| 239 | |
| 240 | void SetRequestHeadersCallback(RequestHeadersCallback callback) override {} |
| 241 | void SetResponseHeadersCallback(ResponseHeadersCallback) override {} |
| 242 | |
| 243 | int ResumeNetworkStart() override; |
| 244 | |
| 245 | void GetConnectionAttempts(ConnectionAttempts* out) const override; |
| 246 | |
| 247 | CreateHelper* websocket_handshake_stream_create_helper() { |
| 248 | return websocket_handshake_stream_create_helper_; |
| 249 | } |
| 250 | |
| 251 | RequestPriority priority() const { return priority_; } |
| 252 | const HttpRequestInfo* request() const { return request_; } |
| 253 | |
| 254 | // Bogus value that will be returned by GetTotalReceivedBytes() if the |
| 255 | // MockNetworkTransaction was started. |
| 256 | static const int64_t kTotalReceivedBytes; |
| 257 | // Bogus value that will be returned by GetTotalSentBytes() if the |
| 258 | // MockNetworkTransaction was started. |
| 259 | static const int64_t kTotalSentBytes; |
| 260 | |
| 261 | private: |
| 262 | int StartInternal(const HttpRequestInfo* request, |
| 263 | CompletionOnceCallback callback, |
| 264 | const NetLogWithSource& net_log); |
| 265 | void CallbackLater(CompletionOnceCallback callback, int result); |
| 266 | void RunCallback(CompletionOnceCallback callback, int result); |
| 267 | |
| 268 | const HttpRequestInfo* request_; |
| 269 | HttpResponseInfo response_; |
| 270 | std::string data_; |
| 271 | int64_t data_cursor_; |
| 272 | int64_t content_length_; |
| 273 | int test_mode_; |
| 274 | RequestPriority priority_; |
| 275 | MockTransactionReadHandler read_handler_; |
| 276 | CreateHelper* websocket_handshake_stream_create_helper_; |
| 277 | BeforeNetworkStartCallback before_network_start_callback_; |
| 278 | base::WeakPtr<MockNetworkLayer> transaction_factory_; |
| 279 | int64_t received_bytes_; |
| 280 | int64_t sent_bytes_; |
| 281 | |
| 282 | // NetLog ID of the fake / non-existent underlying socket used by the |
| 283 | // connection. Requires Start() be passed a NetLogWithSource with a real |
| 284 | // NetLog to |
| 285 | // be initialized. |
| 286 | unsigned int socket_log_id_; |
| 287 | |
| 288 | bool done_reading_called_; |
| 289 | bool reading_; |
| 290 | |
| 291 | CompletionOnceCallback resume_start_callback_; // used for pause and restart. |
| 292 | |
| 293 | base::WeakPtrFactory<MockNetworkTransaction> weak_factory_; |
| 294 | |
| 295 | }; |
| 296 | |
| 297 | class MockNetworkLayer : public HttpTransactionFactory, |
| 298 | public base::SupportsWeakPtr<MockNetworkLayer> { |
| 299 | public: |
| 300 | MockNetworkLayer(); |
| 301 | ~MockNetworkLayer() override; |
| 302 | |
| 303 | int transaction_count() const { return transaction_count_; } |
| 304 | bool done_reading_called() const { return done_reading_called_; } |
| 305 | bool stop_caching_called() const { return stop_caching_called_; } |
| 306 | void TransactionDoneReading(); |
| 307 | void TransactionStopCaching(); |
| 308 | |
| 309 | // Resets the transaction count. Can be called after test setup in order to |
| 310 | // make test expectations independent of how test setup is performed. |
| 311 | void ResetTransactionCount(); |
| 312 | |
| 313 | // Returns the last priority passed to CreateTransaction, or |
| 314 | // DEFAULT_PRIORITY if it hasn't been called yet. |
| 315 | RequestPriority last_create_transaction_priority() const { |
| 316 | return last_create_transaction_priority_; |
| 317 | } |
| 318 | |
| 319 | // Returns the last transaction created by |
| 320 | // CreateTransaction. Returns a NULL WeakPtr if one has not been |
| 321 | // created yet, or the last transaction has been destroyed, or |
| 322 | // ClearLastTransaction() has been called and a new transaction |
| 323 | // hasn't been created yet. |
| 324 | base::WeakPtr<MockNetworkTransaction> last_transaction() { |
| 325 | return last_transaction_; |
| 326 | } |
| 327 | |
| 328 | // Makes last_transaction() return NULL until the next transaction |
| 329 | // is created. |
| 330 | void ClearLastTransaction() { |
| 331 | last_transaction_.reset(); |
| 332 | } |
| 333 | |
| 334 | // HttpTransactionFactory: |
| 335 | int CreateTransaction(RequestPriority priority, |
| 336 | std::unique_ptr<HttpTransaction>* trans) override; |
| 337 | HttpCache* GetCache() override; |
| 338 | HttpNetworkSession* GetSession() override; |
| 339 | |
| 340 | // The caller must guarantee that |clock| will outlive this object. |
| 341 | void SetClock(base::Clock* clock); |
| 342 | base::Clock* clock() const { return clock_; } |
| 343 | |
| 344 | // The current time (will use clock_ if it is non NULL). |
| 345 | base::Time Now(); |
| 346 | |
| 347 | private: |
| 348 | int transaction_count_; |
| 349 | bool done_reading_called_; |
| 350 | bool stop_caching_called_; |
| 351 | RequestPriority last_create_transaction_priority_; |
| 352 | |
| 353 | // By default clock_ is NULL but it can be set to a custom clock by test |
| 354 | // frameworks using SetClock. |
| 355 | base::Clock* clock_; |
| 356 | |
| 357 | base::WeakPtr<MockNetworkTransaction> last_transaction_; |
| 358 | }; |
| 359 | |
| 360 | //----------------------------------------------------------------------------- |
| 361 | // helpers |
| 362 | |
| 363 | // read the transaction completely |
| 364 | int ReadTransaction(HttpTransaction* trans, std::string* result); |
| 365 | |
| 366 | } // namespace net |
| 367 | |
| 368 | #endif // NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ |