|  | // Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_ | 
|  | #define NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_ | 
|  |  | 
|  | #include "net/http/http_transaction.h" | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "base/callback.h" | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/strings/string16.h" | 
|  | #include "net/base/io_buffer.h" | 
|  | #include "net/base/load_flags.h" | 
|  | #include "net/base/net_errors.h" | 
|  | #include "net/base/net_log.h" | 
|  | #include "net/base/request_priority.h" | 
|  | #include "net/base/test_completion_callback.h" | 
|  | #include "net/disk_cache/disk_cache.h" | 
|  | #include "net/http/http_cache.h" | 
|  | #include "net/http/http_request_info.h" | 
|  | #include "net/http/http_response_headers.h" | 
|  | #include "net/http/http_response_info.h" | 
|  |  | 
|  | namespace net { | 
|  | class HttpRequestHeaders; | 
|  | class IOBuffer; | 
|  | struct HttpRequestInfo; | 
|  | } | 
|  |  | 
|  | //----------------------------------------------------------------------------- | 
|  | // mock transaction data | 
|  |  | 
|  | // these flags may be combined to form the test_mode field | 
|  | enum { | 
|  | TEST_MODE_NORMAL = 0, | 
|  | TEST_MODE_SYNC_NET_START = 1 << 0, | 
|  | TEST_MODE_SYNC_NET_READ  = 1 << 1, | 
|  | TEST_MODE_SYNC_CACHE_START = 1 << 2, | 
|  | TEST_MODE_SYNC_CACHE_READ  = 1 << 3, | 
|  | TEST_MODE_SYNC_CACHE_WRITE  = 1 << 4, | 
|  | TEST_MODE_SYNC_ALL = (TEST_MODE_SYNC_NET_START | TEST_MODE_SYNC_NET_READ | | 
|  | TEST_MODE_SYNC_CACHE_START | TEST_MODE_SYNC_CACHE_READ | | 
|  | TEST_MODE_SYNC_CACHE_WRITE), | 
|  | TEST_MODE_SLOW_READ = 1 << 5 | 
|  | }; | 
|  |  | 
|  | typedef void (*MockTransactionHandler)(const net::HttpRequestInfo* request, | 
|  | std::string* response_status, | 
|  | std::string* response_headers, | 
|  | std::string* response_data); | 
|  |  | 
|  | struct MockTransaction { | 
|  | const char* url; | 
|  | const char* method; | 
|  | // If |request_time| is unspecified, the current time will be used. | 
|  | base::Time request_time; | 
|  | const char* request_headers; | 
|  | int load_flags; | 
|  | const char* status; | 
|  | const char* response_headers; | 
|  | // If |response_time| is unspecified, the current time will be used. | 
|  | base::Time response_time; | 
|  | const char* data; | 
|  | int test_mode; | 
|  | MockTransactionHandler handler; | 
|  | net::CertStatus cert_status; | 
|  | // Value returned by MockNetworkTransaction::Start (potentially | 
|  | // asynchronously if |!(test_mode & TEST_MODE_SYNC_NET_START)|.) | 
|  | net::Error return_code; | 
|  | }; | 
|  |  | 
|  | extern const MockTransaction kSimpleGET_Transaction; | 
|  | extern const MockTransaction kSimplePOST_Transaction; | 
|  | extern const MockTransaction kTypicalGET_Transaction; | 
|  | extern const MockTransaction kETagGET_Transaction; | 
|  | extern const MockTransaction kRangeGET_Transaction; | 
|  |  | 
|  | // returns the mock transaction for the given URL | 
|  | const MockTransaction* FindMockTransaction(const GURL& url); | 
|  |  | 
|  | // Add/Remove a mock transaction that can be accessed via FindMockTransaction. | 
|  | // There can be only one MockTransaction associated with a given URL. | 
|  | void AddMockTransaction(const MockTransaction* trans); | 
|  | void RemoveMockTransaction(const MockTransaction* trans); | 
|  |  | 
|  | struct ScopedMockTransaction : MockTransaction { | 
|  | ScopedMockTransaction() { | 
|  | AddMockTransaction(this); | 
|  | } | 
|  | explicit ScopedMockTransaction(const MockTransaction& t) | 
|  | : MockTransaction(t) { | 
|  | AddMockTransaction(this); | 
|  | } | 
|  | ~ScopedMockTransaction() { | 
|  | RemoveMockTransaction(this); | 
|  | } | 
|  | }; | 
|  |  | 
|  | //----------------------------------------------------------------------------- | 
|  | // mock http request | 
|  |  | 
|  | class MockHttpRequest : public net::HttpRequestInfo { | 
|  | public: | 
|  | explicit MockHttpRequest(const MockTransaction& t); | 
|  | }; | 
|  |  | 
|  | //----------------------------------------------------------------------------- | 
|  | // use this class to test completely consuming a transaction | 
|  |  | 
|  | class TestTransactionConsumer { | 
|  | public: | 
|  | TestTransactionConsumer(net::RequestPriority priority, | 
|  | net::HttpTransactionFactory* factory); | 
|  | virtual ~TestTransactionConsumer(); | 
|  |  | 
|  | void Start(const net::HttpRequestInfo* request, | 
|  | const net::BoundNetLog& net_log); | 
|  |  | 
|  | bool is_done() const { return state_ == DONE; } | 
|  | int error() const { return error_; } | 
|  |  | 
|  | const net::HttpResponseInfo* response_info() const { | 
|  | return trans_->GetResponseInfo(); | 
|  | } | 
|  | const std::string& content() const { return content_; } | 
|  |  | 
|  | private: | 
|  | enum State { | 
|  | IDLE, | 
|  | STARTING, | 
|  | READING, | 
|  | DONE | 
|  | }; | 
|  |  | 
|  | void DidStart(int result); | 
|  | void DidRead(int result); | 
|  | void DidFinish(int result); | 
|  | void Read(); | 
|  |  | 
|  | void OnIOComplete(int result); | 
|  |  | 
|  | State state_; | 
|  | scoped_ptr<net::HttpTransaction> trans_; | 
|  | std::string content_; | 
|  | scoped_refptr<net::IOBuffer> read_buf_; | 
|  | int error_; | 
|  |  | 
|  | static int quit_counter_; | 
|  | }; | 
|  |  | 
|  | //----------------------------------------------------------------------------- | 
|  | // mock network layer | 
|  |  | 
|  | class MockNetworkLayer; | 
|  |  | 
|  | // This transaction class inspects the available set of mock transactions to | 
|  | // find data for the request URL.  It supports IO operations that complete | 
|  | // synchronously or asynchronously to help exercise different code paths in the | 
|  | // HttpCache implementation. | 
|  | class MockNetworkTransaction | 
|  | : public net::HttpTransaction, | 
|  | public base::SupportsWeakPtr<MockNetworkTransaction> { | 
|  | typedef net::WebSocketHandshakeStreamBase::CreateHelper CreateHelper; | 
|  | public: | 
|  | MockNetworkTransaction(net::RequestPriority priority, | 
|  | MockNetworkLayer* factory); | 
|  | ~MockNetworkTransaction() override; | 
|  |  | 
|  | int Start(const net::HttpRequestInfo* request, | 
|  | const net::CompletionCallback& callback, | 
|  | const net::BoundNetLog& net_log) override; | 
|  |  | 
|  | int RestartIgnoringLastError( | 
|  | const net::CompletionCallback& callback) override; | 
|  |  | 
|  | int RestartWithCertificate(net::X509Certificate* client_cert, | 
|  | const net::CompletionCallback& callback) override; | 
|  |  | 
|  | int RestartWithAuth(const net::AuthCredentials& credentials, | 
|  | const net::CompletionCallback& callback) override; | 
|  |  | 
|  | bool IsReadyToRestartForAuth() override; | 
|  |  | 
|  | int Read(net::IOBuffer* buf, | 
|  | int buf_len, | 
|  | const net::CompletionCallback& callback) override; | 
|  |  | 
|  | void StopCaching() override; | 
|  |  | 
|  | bool GetFullRequestHeaders(net::HttpRequestHeaders* headers) const override; | 
|  |  | 
|  | int64 GetTotalReceivedBytes() const override; | 
|  |  | 
|  | void DoneReading() override; | 
|  |  | 
|  | const net::HttpResponseInfo* GetResponseInfo() const override; | 
|  |  | 
|  | net::LoadState GetLoadState() const override; | 
|  |  | 
|  | net::UploadProgress GetUploadProgress() const override; | 
|  |  | 
|  | void SetQuicServerInfo(net::QuicServerInfo* quic_server_info) override; | 
|  |  | 
|  | bool GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override; | 
|  |  | 
|  | void SetPriority(net::RequestPriority priority) override; | 
|  |  | 
|  | void SetWebSocketHandshakeStreamCreateHelper( | 
|  | CreateHelper* create_helper) override; | 
|  |  | 
|  | void SetBeforeNetworkStartCallback( | 
|  | const BeforeNetworkStartCallback& callback) override; | 
|  |  | 
|  | void SetBeforeProxyHeadersSentCallback( | 
|  | const BeforeProxyHeadersSentCallback& callback) override; | 
|  |  | 
|  | int ResumeNetworkStart() override; | 
|  |  | 
|  | CreateHelper* websocket_handshake_stream_create_helper() { | 
|  | return websocket_handshake_stream_create_helper_; | 
|  | } | 
|  | net::RequestPriority priority() const { return priority_; } | 
|  | const net::HttpRequestInfo* request() const { return request_; } | 
|  |  | 
|  | private: | 
|  | int StartInternal(const net::HttpRequestInfo* request, | 
|  | const net::CompletionCallback& callback, | 
|  | const net::BoundNetLog& net_log); | 
|  | void CallbackLater(const net::CompletionCallback& callback, int result); | 
|  | void RunCallback(const net::CompletionCallback& callback, int result); | 
|  |  | 
|  | const net::HttpRequestInfo* request_; | 
|  | net::HttpResponseInfo response_; | 
|  | std::string data_; | 
|  | int data_cursor_; | 
|  | int test_mode_; | 
|  | net::RequestPriority priority_; | 
|  | CreateHelper* websocket_handshake_stream_create_helper_; | 
|  | base::WeakPtr<MockNetworkLayer> transaction_factory_; | 
|  | int64 received_bytes_; | 
|  |  | 
|  | // NetLog ID of the fake / non-existent underlying socket used by the | 
|  | // connection. Requires Start() be passed a BoundNetLog with a real NetLog to | 
|  | // be initialized. | 
|  | unsigned int socket_log_id_; | 
|  |  | 
|  | base::WeakPtrFactory<MockNetworkTransaction> weak_factory_; | 
|  |  | 
|  | }; | 
|  |  | 
|  | class MockNetworkLayer : public net::HttpTransactionFactory, | 
|  | public base::SupportsWeakPtr<MockNetworkLayer> { | 
|  | public: | 
|  | MockNetworkLayer(); | 
|  | ~MockNetworkLayer() override; | 
|  |  | 
|  | int transaction_count() const { return transaction_count_; } | 
|  | bool done_reading_called() const { return done_reading_called_; } | 
|  | bool stop_caching_called() const { return stop_caching_called_; } | 
|  | void TransactionDoneReading(); | 
|  | void TransactionStopCaching(); | 
|  |  | 
|  | // Returns the last priority passed to CreateTransaction, or | 
|  | // DEFAULT_PRIORITY if it hasn't been called yet. | 
|  | net::RequestPriority last_create_transaction_priority() const { | 
|  | return last_create_transaction_priority_; | 
|  | } | 
|  |  | 
|  | // Returns the last transaction created by | 
|  | // CreateTransaction. Returns a NULL WeakPtr if one has not been | 
|  | // created yet, or the last transaction has been destroyed, or | 
|  | // ClearLastTransaction() has been called and a new transaction | 
|  | // hasn't been created yet. | 
|  | base::WeakPtr<MockNetworkTransaction> last_transaction() { | 
|  | return last_transaction_; | 
|  | } | 
|  |  | 
|  | // Makes last_transaction() return NULL until the next transaction | 
|  | // is created. | 
|  | void ClearLastTransaction() { | 
|  | last_transaction_.reset(); | 
|  | } | 
|  |  | 
|  | // net::HttpTransactionFactory: | 
|  | int CreateTransaction(net::RequestPriority priority, | 
|  | scoped_ptr<net::HttpTransaction>* trans) override; | 
|  | net::HttpCache* GetCache() override; | 
|  | net::HttpNetworkSession* GetSession() override; | 
|  |  | 
|  | // The caller must guarantee that |clock| will outlive this object. | 
|  | void SetClock(base::Clock* clock); | 
|  | base::Clock* clock() const { return clock_; } | 
|  |  | 
|  | // The current time (will use clock_ if it is non NULL). | 
|  | base::Time Now(); | 
|  |  | 
|  | private: | 
|  | int transaction_count_; | 
|  | bool done_reading_called_; | 
|  | bool stop_caching_called_; | 
|  | net::RequestPriority last_create_transaction_priority_; | 
|  |  | 
|  | // By default clock_ is NULL but it can be set to a custom clock by test | 
|  | // frameworks using SetClock. | 
|  | base::Clock* clock_; | 
|  |  | 
|  | base::WeakPtr<MockNetworkTransaction> last_transaction_; | 
|  | }; | 
|  |  | 
|  | //----------------------------------------------------------------------------- | 
|  | // helpers | 
|  |  | 
|  | // read the transaction completely | 
|  | int ReadTransaction(net::HttpTransaction* trans, std::string* result); | 
|  |  | 
|  | #endif  // NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_ |