David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 1 | // Copyright (c) 2012 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_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_ |
| 6 | #define NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_ |
| 7 | |
| 8 | #include <list> |
| 9 | #include <map> |
| 10 | #include <string> |
| 11 | #include <utility> |
| 12 | |
| 13 | #include "base/compiler_specific.h" |
| 14 | #include "base/threading/non_thread_safe.h" |
| 15 | #include "googleurl/src/gurl.h" |
| 16 | #include "net/http/http_request_headers.h" |
| 17 | #include "net/url_request/url_fetcher_factory.h" |
| 18 | #include "net/url_request/url_request_status.h" |
| 19 | |
| 20 | namespace net { |
| 21 | |
| 22 | // Changes URLFetcher's Factory for the lifetime of the object. |
| 23 | // Note that this scoper cannot be nested (to make it even harder to misuse). |
| 24 | class ScopedURLFetcherFactory : public base::NonThreadSafe { |
| 25 | public: |
| 26 | explicit ScopedURLFetcherFactory(URLFetcherFactory* factory); |
| 27 | virtual ~ScopedURLFetcherFactory(); |
| 28 | |
| 29 | private: |
| 30 | DISALLOW_COPY_AND_ASSIGN(ScopedURLFetcherFactory); |
| 31 | }; |
| 32 | |
| 33 | // TestURLFetcher and TestURLFetcherFactory are used for testing consumers of |
| 34 | // URLFetcher. TestURLFetcherFactory is a URLFetcherFactory that creates |
| 35 | // TestURLFetchers. TestURLFetcher::Start is overriden to do nothing. It is |
| 36 | // expected that you'll grab the delegate from the TestURLFetcher and invoke |
| 37 | // the callback method when appropriate. In this way it's easy to mock a |
| 38 | // URLFetcher. |
| 39 | // Typical usage: |
| 40 | // // TestURLFetcher requires a MessageLoop. |
| 41 | // MessageLoop message_loop; |
| 42 | // // And an IO thread to release URLRequestContextGetter in URLFetcher::Core. |
| 43 | // BrowserThreadImpl io_thread(BrowserThread::IO, &message_loop); |
| 44 | // // Create factory (it automatically sets itself as URLFetcher's factory). |
| 45 | // TestURLFetcherFactory factory; |
| 46 | // // Do something that triggers creation of a URLFetcher. |
| 47 | // ... |
| 48 | // TestURLFetcher* fetcher = factory.GetFetcherByID(expected_id); |
| 49 | // DCHECK(fetcher); |
| 50 | // // Notify delegate with whatever data you want. |
| 51 | // fetcher->delegate()->OnURLFetchComplete(...); |
| 52 | // // Make sure consumer of URLFetcher does the right thing. |
| 53 | // ... |
| 54 | // |
| 55 | // Note: if you don't know when your request objects will be created you |
| 56 | // might want to use the FakeURLFetcher and FakeURLFetcherFactory classes |
| 57 | // below. |
| 58 | |
| 59 | class TestURLFetcherFactory; |
| 60 | class TestURLFetcher : public URLFetcher { |
| 61 | public: |
| 62 | // Interface for tests to intercept production code classes using URLFetcher. |
| 63 | // Allows even-driven mock server classes to analyze the correctness of |
| 64 | // requests / uploads events and forge responses back at the right moment. |
| 65 | class DelegateForTests { |
| 66 | public: |
| 67 | // Callback issued correspondingly to the call to the |Start()| method. |
| 68 | virtual void OnRequestStart(int fetcher_id) = 0; |
| 69 | |
| 70 | // Callback issued correspondingly to the call to |AppendChunkToUpload|. |
| 71 | // Uploaded chunks can be retrieved with the |upload_chunks()| getter. |
| 72 | virtual void OnChunkUpload(int fetcher_id) = 0; |
| 73 | |
| 74 | // Callback issued correspondingly to the destructor. |
| 75 | virtual void OnRequestEnd(int fetcher_id) = 0; |
| 76 | }; |
| 77 | |
| 78 | TestURLFetcher(int id, |
| 79 | const GURL& url, |
| 80 | URLFetcherDelegate* d); |
| 81 | virtual ~TestURLFetcher(); |
| 82 | |
| 83 | // URLFetcher implementation |
| 84 | virtual void SetUploadData(const std::string& upload_content_type, |
| 85 | const std::string& upload_content) OVERRIDE; |
| 86 | virtual void SetChunkedUpload( |
| 87 | const std::string& upload_content_type) OVERRIDE; |
| 88 | // Overriden to cache the chunks uploaded. Caller can read back the uploaded |
| 89 | // chunks with the upload_chunks() accessor. |
| 90 | virtual void AppendChunkToUpload(const std::string& data, |
| 91 | bool is_last_chunk) OVERRIDE; |
| 92 | virtual void SetLoadFlags(int load_flags) OVERRIDE; |
| 93 | virtual int GetLoadFlags() const OVERRIDE; |
| 94 | virtual void SetReferrer(const std::string& referrer) OVERRIDE; |
| 95 | virtual void SetExtraRequestHeaders( |
| 96 | const std::string& extra_request_headers) OVERRIDE; |
| 97 | virtual void AddExtraRequestHeader(const std::string& header_line) OVERRIDE; |
| 98 | virtual void GetExtraRequestHeaders( |
| 99 | HttpRequestHeaders* headers) const OVERRIDE; |
| 100 | virtual void SetRequestContext( |
| 101 | URLRequestContextGetter* request_context_getter) OVERRIDE; |
| 102 | virtual void SetFirstPartyForCookies( |
| 103 | const GURL& first_party_for_cookies) OVERRIDE; |
| 104 | virtual void SetURLRequestUserData( |
| 105 | const void* key, |
| 106 | const CreateDataCallback& create_data_callback) OVERRIDE; |
| 107 | virtual void SetStopOnRedirect(bool stop_on_redirect) OVERRIDE; |
| 108 | virtual void SetAutomaticallyRetryOn5xx(bool retry) OVERRIDE; |
| 109 | virtual void SetMaxRetriesOn5xx(int max_retries) OVERRIDE; |
| 110 | virtual int GetMaxRetriesOn5xx() const OVERRIDE; |
| 111 | virtual base::TimeDelta GetBackoffDelay() const OVERRIDE; |
| 112 | virtual void SetAutomaticallyRetryOnNetworkChanges(int max_retries) OVERRIDE; |
| 113 | virtual void SaveResponseToFileAtPath( |
| 114 | const FilePath& file_path, |
| 115 | scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE; |
| 116 | virtual void SaveResponseToTemporaryFile( |
| 117 | scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE; |
| 118 | #if defined(COBALT) |
| 119 | virtual void DiscardResponse() OVERRIDE; |
| 120 | #endif |
| 121 | virtual HttpResponseHeaders* GetResponseHeaders() const OVERRIDE; |
| 122 | virtual HostPortPair GetSocketAddress() const OVERRIDE; |
| 123 | virtual bool WasFetchedViaProxy() const OVERRIDE; |
| 124 | virtual void Start() OVERRIDE; |
| 125 | |
| 126 | // URL we were created with. Because of how we're using URLFetcher GetURL() |
| 127 | // always returns an empty URL. Chances are you'll want to use |
| 128 | // GetOriginalURL() in your tests. |
| 129 | virtual const GURL& GetOriginalURL() const OVERRIDE; |
| 130 | virtual const GURL& GetURL() const OVERRIDE; |
| 131 | virtual const URLRequestStatus& GetStatus() const OVERRIDE; |
| 132 | virtual int GetResponseCode() const OVERRIDE; |
| 133 | virtual const ResponseCookies& GetCookies() const OVERRIDE; |
| 134 | virtual bool FileErrorOccurred( |
| 135 | base::PlatformFileError* out_error_code) const OVERRIDE; |
| 136 | virtual void ReceivedContentWasMalformed() OVERRIDE; |
| 137 | // Override response access functions to return fake data. |
| 138 | virtual bool GetResponseAsString( |
| 139 | std::string* out_response_string) const OVERRIDE; |
| 140 | virtual bool GetResponseAsFilePath( |
| 141 | bool take_ownership, FilePath* out_response_path) const OVERRIDE; |
| 142 | |
| 143 | // Sets owner of this class. Set it to a non-NULL value if you want |
| 144 | // to automatically unregister this fetcher from the owning factory |
| 145 | // upon destruction. |
| 146 | void set_owner(TestURLFetcherFactory* owner) { owner_ = owner; } |
| 147 | |
| 148 | // Unique ID in our factory. |
| 149 | int id() const { return id_; } |
| 150 | |
| 151 | // Returns the data uploaded on this URLFetcher. |
| 152 | const std::string& upload_data() const { return upload_data_; } |
| 153 | |
| 154 | // Returns the chunks of data uploaded on this URLFetcher. |
| 155 | const std::list<std::string>& upload_chunks() const { return chunks_; } |
| 156 | |
| 157 | // Checks whether the last call to |AppendChunkToUpload(...)| was final. |
| 158 | bool did_receive_last_chunk() const { return did_receive_last_chunk_; } |
| 159 | |
| 160 | // Returns the delegate installed on the URLFetcher. |
| 161 | URLFetcherDelegate* delegate() const { return delegate_; } |
| 162 | |
| 163 | void set_url(const GURL& url) { fake_url_ = url; } |
| 164 | void set_status(const URLRequestStatus& status); |
| 165 | void set_response_code(int response_code) { |
| 166 | fake_response_code_ = response_code; |
| 167 | } |
| 168 | void set_cookies(const ResponseCookies& c) { fake_cookies_ = c; } |
| 169 | void set_was_fetched_via_proxy(bool flag); |
| 170 | void set_response_headers(scoped_refptr<HttpResponseHeaders> headers); |
| 171 | void set_backoff_delay(base::TimeDelta backoff_delay); |
| 172 | void SetDelegateForTests(DelegateForTests* delegate_for_tests); |
| 173 | |
| 174 | // Set string data. |
| 175 | void SetResponseString(const std::string& response); |
| 176 | |
| 177 | // Set File data. |
| 178 | void SetResponseFilePath(const FilePath& path); |
| 179 | |
| 180 | private: |
| 181 | enum ResponseDestinationType { |
| 182 | STRING, // Default: In a std::string |
| 183 | TEMP_FILE // Write to a temp file |
| 184 | }; |
| 185 | |
| 186 | TestURLFetcherFactory* owner_; |
| 187 | const int id_; |
| 188 | const GURL original_url_; |
| 189 | URLFetcherDelegate* delegate_; |
| 190 | DelegateForTests* delegate_for_tests_; |
| 191 | std::string upload_data_; |
| 192 | std::list<std::string> chunks_; |
| 193 | bool did_receive_last_chunk_; |
| 194 | |
| 195 | // User can use set_* methods to provide values returned by getters. |
| 196 | // Setting the real values is not possible, because the real class |
| 197 | // has no setters. The data is a private member of a class defined |
| 198 | // in a .cc file, so we can't get at it with friendship. |
| 199 | int fake_load_flags_; |
| 200 | GURL fake_url_; |
| 201 | URLRequestStatus fake_status_; |
| 202 | int fake_response_code_; |
| 203 | ResponseCookies fake_cookies_; |
| 204 | ResponseDestinationType fake_response_destination_; |
| 205 | std::string fake_response_string_; |
| 206 | FilePath fake_response_file_path_; |
| 207 | bool fake_was_fetched_via_proxy_; |
| 208 | scoped_refptr<HttpResponseHeaders> fake_response_headers_; |
| 209 | HttpRequestHeaders fake_extra_request_headers_; |
| 210 | int fake_max_retries_; |
| 211 | base::TimeDelta fake_backoff_delay_; |
| 212 | |
| 213 | DISALLOW_COPY_AND_ASSIGN(TestURLFetcher); |
| 214 | }; |
| 215 | |
| 216 | typedef TestURLFetcher::DelegateForTests TestURLFetcherDelegateForTests; |
| 217 | |
| 218 | // Simple URLFetcherFactory method that creates TestURLFetchers. All fetchers |
| 219 | // are registered in a map by the id passed to the create method. |
| 220 | // Optionally, a fetcher may be automatically unregistered from the map upon |
| 221 | // its destruction. |
| 222 | class TestURLFetcherFactory : public URLFetcherFactory, |
| 223 | public ScopedURLFetcherFactory { |
| 224 | public: |
| 225 | TestURLFetcherFactory(); |
| 226 | virtual ~TestURLFetcherFactory(); |
| 227 | |
| 228 | virtual URLFetcher* CreateURLFetcher( |
| 229 | int id, |
| 230 | const GURL& url, |
| 231 | URLFetcher::RequestType request_type, |
| 232 | URLFetcherDelegate* d) OVERRIDE; |
| 233 | TestURLFetcher* GetFetcherByID(int id) const; |
| 234 | void RemoveFetcherFromMap(int id); |
| 235 | void SetDelegateForTests(TestURLFetcherDelegateForTests* delegate_for_tests); |
| 236 | void set_remove_fetcher_on_delete(bool remove_fetcher_on_delete) { |
| 237 | remove_fetcher_on_delete_ = remove_fetcher_on_delete; |
| 238 | } |
| 239 | |
| 240 | private: |
| 241 | // Maps from id passed to create to the returned URLFetcher. |
| 242 | typedef std::map<int, TestURLFetcher*> Fetchers; |
| 243 | Fetchers fetchers_; |
| 244 | TestURLFetcherDelegateForTests* delegate_for_tests_; |
| 245 | // Whether to automatically unregister a fetcher from this factory upon its |
| 246 | // destruction, false by default. |
| 247 | bool remove_fetcher_on_delete_; |
| 248 | |
| 249 | DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory); |
| 250 | }; |
| 251 | |
| 252 | // The FakeURLFetcher and FakeURLFetcherFactory classes are similar to the |
| 253 | // ones above but don't require you to know when exactly the URLFetcher objects |
| 254 | // will be created. |
| 255 | // |
| 256 | // These classes let you set pre-baked HTTP responses for particular URLs. |
| 257 | // E.g., if the user requests http://a.com/ then respond with an HTTP/500. |
| 258 | // |
| 259 | // We assume that the thread that is calling Start() on the URLFetcher object |
| 260 | // has a message loop running. |
| 261 | // |
| 262 | // This class is not thread-safe. You should not call SetFakeResponse or |
| 263 | // ClearFakeResponse at the same time you call CreateURLFetcher. However, it is |
| 264 | // OK to start URLFetcher objects while setting or clearning fake responses |
| 265 | // since already created URLFetcher objects will not be affected by any changes |
| 266 | // made to the fake responses (once a URLFetcher object is created you cannot |
| 267 | // change its fake response). |
| 268 | // |
| 269 | // Example usage: |
| 270 | // FakeURLFetcherFactory factory; |
| 271 | // |
| 272 | // // You know that class SomeService will request url http://a.com/ and you |
| 273 | // // want to test the service class by returning an error. |
| 274 | // factory.SetFakeResponse("http://a.com/", "", false); |
| 275 | // // But if the service requests http://b.com/asdf you want to respond with |
| 276 | // // a simple html page and an HTTP/200 code. |
| 277 | // factory.SetFakeResponse("http://b.com/asdf", |
| 278 | // "<html><body>hello world</body></html>", |
| 279 | // true); |
| 280 | // |
| 281 | // SomeService service; |
| 282 | // service.Run(); // Will eventually request these two URLs. |
| 283 | |
| 284 | class FakeURLFetcherFactory : public URLFetcherFactory, |
| 285 | public ScopedURLFetcherFactory { |
| 286 | public: |
| 287 | FakeURLFetcherFactory(); |
| 288 | // FakeURLFetcherFactory that will delegate creating URLFetcher for unknown |
| 289 | // url to the given factory. |
| 290 | explicit FakeURLFetcherFactory(URLFetcherFactory* default_factory); |
| 291 | virtual ~FakeURLFetcherFactory(); |
| 292 | |
| 293 | // If no fake response is set for the given URL this method will delegate the |
| 294 | // call to |default_factory_| if it is not NULL, or return NULL if it is |
| 295 | // NULL. |
| 296 | // Otherwise, it will return a URLFetcher object which will respond with the |
| 297 | // pre-baked response that the client has set by calling SetFakeResponse(). |
| 298 | virtual URLFetcher* CreateURLFetcher( |
| 299 | int id, |
| 300 | const GURL& url, |
| 301 | URLFetcher::RequestType request_type, |
| 302 | URLFetcherDelegate* d) OVERRIDE; |
| 303 | |
| 304 | // Sets the fake response for a given URL. If success is true we will serve |
| 305 | // an HTTP/200 and an HTTP/500 otherwise. The |response_data| may be empty. |
| 306 | void SetFakeResponse(const std::string& url, |
| 307 | const std::string& response_data, |
| 308 | bool success); |
| 309 | |
| 310 | // Clear all the fake responses that were previously set via |
| 311 | // SetFakeResponse(). |
| 312 | void ClearFakeResponses(); |
| 313 | |
| 314 | private: |
| 315 | typedef std::map<GURL, std::pair<std::string, bool> > FakeResponseMap; |
| 316 | FakeResponseMap fake_responses_; |
| 317 | URLFetcherFactory* default_factory_; |
| 318 | |
| 319 | DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory); |
| 320 | }; |
| 321 | |
| 322 | // This is an implementation of URLFetcherFactory that will create a |
| 323 | // URLFetcherImpl. It can be use in conjunction with a FakeURLFetcherFactory in |
| 324 | // integration tests to control the behavior of some requests but execute |
| 325 | // all the other ones. |
| 326 | class URLFetcherImplFactory : public URLFetcherFactory { |
| 327 | public: |
| 328 | URLFetcherImplFactory(); |
| 329 | virtual ~URLFetcherImplFactory(); |
| 330 | |
| 331 | // This method will create a real URLFetcher. |
| 332 | virtual URLFetcher* CreateURLFetcher( |
| 333 | int id, |
| 334 | const GURL& url, |
| 335 | URLFetcher::RequestType request_type, |
| 336 | URLFetcherDelegate* d) OVERRIDE; |
| 337 | |
| 338 | }; |
| 339 | |
| 340 | } // namespace net |
| 341 | |
| 342 | #endif // NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_ |