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.
5 #ifndef NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_
6 #define NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_
13 #include "base/basictypes.h"
14 #include "base/callback.h"
15 #include "base/compiler_specific.h"
16 #include "base/files/file_path.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/threading/non_thread_safe.h"
20 #include "net/http/http_request_headers.h"
21 #include "net/http/http_status_code.h"
22 #include "net/url_request/url_fetcher_factory.h"
23 #include "net/url_request/url_request_status.h"
28 // Changes URLFetcher's Factory for the lifetime of the object.
29 // Note that this scoper cannot be nested (to make it even harder to misuse).
30 class ScopedURLFetcherFactory : public base::NonThreadSafe {
32 explicit ScopedURLFetcherFactory(URLFetcherFactory* factory);
33 virtual ~ScopedURLFetcherFactory();
36 DISALLOW_COPY_AND_ASSIGN(ScopedURLFetcherFactory);
39 // TestURLFetcher and TestURLFetcherFactory are used for testing consumers of
40 // URLFetcher. TestURLFetcherFactory is a URLFetcherFactory that creates
41 // TestURLFetchers. TestURLFetcher::Start is overriden to do nothing. It is
42 // expected that you'll grab the delegate from the TestURLFetcher and invoke
43 // the callback method when appropriate. In this way it's easy to mock a
46 // // TestURLFetcher requires a MessageLoop.
47 // MessageLoop message_loop;
48 // // And an IO thread to release URLRequestContextGetter in URLFetcher::Core.
49 // BrowserThreadImpl io_thread(BrowserThread::IO, &message_loop);
50 // // Create factory (it automatically sets itself as URLFetcher's factory).
51 // TestURLFetcherFactory factory;
52 // // Do something that triggers creation of a URLFetcher.
54 // TestURLFetcher* fetcher = factory.GetFetcherByID(expected_id);
56 // // Notify delegate with whatever data you want.
57 // fetcher->delegate()->OnURLFetchComplete(...);
58 // // Make sure consumer of URLFetcher does the right thing.
61 // Note: if you don't know when your request objects will be created you
62 // might want to use the FakeURLFetcher and FakeURLFetcherFactory classes
65 class TestURLFetcherFactory;
66 class TestURLFetcher : public URLFetcher {
68 // Interface for tests to intercept production code classes using URLFetcher.
69 // Allows even-driven mock server classes to analyze the correctness of
70 // requests / uploads events and forge responses back at the right moment.
71 class DelegateForTests {
73 // Callback issued correspondingly to the call to the |Start()| method.
74 virtual void OnRequestStart(int fetcher_id) = 0;
76 // Callback issued correspondingly to the call to |AppendChunkToUpload|.
77 // Uploaded chunks can be retrieved with the |upload_chunks()| getter.
78 virtual void OnChunkUpload(int fetcher_id) = 0;
80 // Callback issued correspondingly to the destructor.
81 virtual void OnRequestEnd(int fetcher_id) = 0;
84 TestURLFetcher(int id,
86 URLFetcherDelegate* d);
87 virtual ~TestURLFetcher();
89 // URLFetcher implementation
90 virtual void SetUploadData(const std::string& upload_content_type,
91 const std::string& upload_content) OVERRIDE;
92 virtual void SetUploadFilePath(
93 const std::string& upload_content_type,
94 const base::FilePath& file_path,
97 scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
98 virtual void SetChunkedUpload(
99 const std::string& upload_content_type) OVERRIDE;
100 // Overriden to cache the chunks uploaded. Caller can read back the uploaded
101 // chunks with the upload_chunks() accessor.
102 virtual void AppendChunkToUpload(const std::string& data,
103 bool is_last_chunk) OVERRIDE;
104 virtual void SetLoadFlags(int load_flags) OVERRIDE;
105 virtual int GetLoadFlags() const OVERRIDE;
106 virtual void SetReferrer(const std::string& referrer) OVERRIDE;
107 virtual void SetExtraRequestHeaders(
108 const std::string& extra_request_headers) OVERRIDE;
109 virtual void AddExtraRequestHeader(const std::string& header_line) OVERRIDE;
110 virtual void GetExtraRequestHeaders(
111 HttpRequestHeaders* headers) const OVERRIDE;
112 virtual void SetRequestContext(
113 URLRequestContextGetter* request_context_getter) OVERRIDE;
114 virtual void SetFirstPartyForCookies(
115 const GURL& first_party_for_cookies) OVERRIDE;
116 virtual void SetURLRequestUserData(
118 const CreateDataCallback& create_data_callback) OVERRIDE;
119 virtual void SetStopOnRedirect(bool stop_on_redirect) OVERRIDE;
120 virtual void SetAutomaticallyRetryOn5xx(bool retry) OVERRIDE;
121 virtual void SetMaxRetriesOn5xx(int max_retries) OVERRIDE;
122 virtual int GetMaxRetriesOn5xx() const OVERRIDE;
123 virtual base::TimeDelta GetBackoffDelay() const OVERRIDE;
124 virtual void SetAutomaticallyRetryOnNetworkChanges(int max_retries) OVERRIDE;
125 virtual void SaveResponseToFileAtPath(
126 const base::FilePath& file_path,
127 scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
128 virtual void SaveResponseToTemporaryFile(
129 scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
130 virtual void SaveResponseWithWriter(
131 scoped_ptr<URLFetcherResponseWriter> response_writer) OVERRIDE;
132 virtual HttpResponseHeaders* GetResponseHeaders() const OVERRIDE;
133 virtual HostPortPair GetSocketAddress() const OVERRIDE;
134 virtual bool WasFetchedViaProxy() const OVERRIDE;
135 virtual void Start() OVERRIDE;
137 // URL we were created with. Because of how we're using URLFetcher GetURL()
138 // always returns an empty URL. Chances are you'll want to use
139 // GetOriginalURL() in your tests.
140 virtual const GURL& GetOriginalURL() const OVERRIDE;
141 virtual const GURL& GetURL() const OVERRIDE;
142 virtual const URLRequestStatus& GetStatus() const OVERRIDE;
143 virtual int GetResponseCode() const OVERRIDE;
144 virtual const ResponseCookies& GetCookies() const OVERRIDE;
145 virtual void ReceivedContentWasMalformed() OVERRIDE;
146 // Override response access functions to return fake data.
147 virtual bool GetResponseAsString(
148 std::string* out_response_string) const OVERRIDE;
149 virtual bool GetResponseAsFilePath(
150 bool take_ownership, base::FilePath* out_response_path) const OVERRIDE;
152 // Sets owner of this class. Set it to a non-NULL value if you want
153 // to automatically unregister this fetcher from the owning factory
155 void set_owner(TestURLFetcherFactory* owner) { owner_ = owner; }
157 // Unique ID in our factory.
158 int id() const { return id_; }
160 // Returns the data uploaded on this URLFetcher.
161 const std::string& upload_data() const { return upload_data_; }
162 const base::FilePath& upload_file_path() const { return upload_file_path_; }
164 // Returns the chunks of data uploaded on this URLFetcher.
165 const std::list<std::string>& upload_chunks() const { return chunks_; }
167 // Checks whether the last call to |AppendChunkToUpload(...)| was final.
168 bool did_receive_last_chunk() const { return did_receive_last_chunk_; }
170 // Returns the delegate installed on the URLFetcher.
171 URLFetcherDelegate* delegate() const { return delegate_; }
173 void set_url(const GURL& url) { fake_url_ = url; }
174 void set_status(const URLRequestStatus& status);
175 void set_response_code(int response_code) {
176 fake_response_code_ = response_code;
178 void set_cookies(const ResponseCookies& c) { fake_cookies_ = c; }
179 void set_was_fetched_via_proxy(bool flag);
180 void set_response_headers(scoped_refptr<HttpResponseHeaders> headers);
181 void set_backoff_delay(base::TimeDelta backoff_delay);
182 void SetDelegateForTests(DelegateForTests* delegate_for_tests);
185 void SetResponseString(const std::string& response);
188 void SetResponseFilePath(const base::FilePath& path);
191 enum ResponseDestinationType {
192 STRING, // Default: In a std::string
193 TEMP_FILE // Write to a temp file
196 TestURLFetcherFactory* owner_;
198 const GURL original_url_;
199 URLFetcherDelegate* delegate_;
200 DelegateForTests* delegate_for_tests_;
201 std::string upload_data_;
202 base::FilePath upload_file_path_;
203 std::list<std::string> chunks_;
204 bool did_receive_last_chunk_;
206 // User can use set_* methods to provide values returned by getters.
207 // Setting the real values is not possible, because the real class
208 // has no setters. The data is a private member of a class defined
209 // in a .cc file, so we can't get at it with friendship.
210 int fake_load_flags_;
212 URLRequestStatus fake_status_;
213 int fake_response_code_;
214 ResponseCookies fake_cookies_;
215 ResponseDestinationType fake_response_destination_;
216 std::string fake_response_string_;
217 base::FilePath fake_response_file_path_;
218 bool fake_was_fetched_via_proxy_;
219 scoped_refptr<HttpResponseHeaders> fake_response_headers_;
220 HttpRequestHeaders fake_extra_request_headers_;
221 int fake_max_retries_;
222 base::TimeDelta fake_backoff_delay_;
224 DISALLOW_COPY_AND_ASSIGN(TestURLFetcher);
227 typedef TestURLFetcher::DelegateForTests TestURLFetcherDelegateForTests;
229 // Simple URLFetcherFactory method that creates TestURLFetchers. All fetchers
230 // are registered in a map by the id passed to the create method.
231 // Optionally, a fetcher may be automatically unregistered from the map upon
233 class TestURLFetcherFactory : public URLFetcherFactory,
234 public ScopedURLFetcherFactory {
236 TestURLFetcherFactory();
237 virtual ~TestURLFetcherFactory();
239 virtual URLFetcher* CreateURLFetcher(
242 URLFetcher::RequestType request_type,
243 URLFetcherDelegate* d) OVERRIDE;
244 TestURLFetcher* GetFetcherByID(int id) const;
245 void RemoveFetcherFromMap(int id);
246 void SetDelegateForTests(TestURLFetcherDelegateForTests* delegate_for_tests);
247 void set_remove_fetcher_on_delete(bool remove_fetcher_on_delete) {
248 remove_fetcher_on_delete_ = remove_fetcher_on_delete;
252 // Maps from id passed to create to the returned URLFetcher.
253 typedef std::map<int, TestURLFetcher*> Fetchers;
255 TestURLFetcherDelegateForTests* delegate_for_tests_;
256 // Whether to automatically unregister a fetcher from this factory upon its
257 // destruction, false by default.
258 bool remove_fetcher_on_delete_;
260 DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory);
263 // The FakeURLFetcher and FakeURLFetcherFactory classes are similar to the
264 // ones above but don't require you to know when exactly the URLFetcher objects
267 // These classes let you set pre-baked HTTP responses for particular URLs.
268 // E.g., if the user requests http://a.com/ then respond with an HTTP/500.
270 // We assume that the thread that is calling Start() on the URLFetcher object
271 // has a message loop running.
273 // FakeURLFetcher can be used to create a URLFetcher that will emit a fake
274 // response when started. This class can be used in place of an actual
278 // FakeURLFetcher fake_fetcher("http://a.com", some_delegate,
279 // "<html><body>hello world</body></html>",
282 // // Will schedule a call to some_delegate->OnURLFetchComplete(&fake_fetcher).
283 // fake_fetcher.Start();
284 class FakeURLFetcher : public TestURLFetcher {
286 // Normal URL fetcher constructor but also takes in a pre-baked response.
287 FakeURLFetcher(const GURL& url,
288 URLFetcherDelegate* d,
289 const std::string& response_data,
290 HttpStatusCode response_code);
292 // Start the request. This will call the given delegate asynchronously
293 // with the pre-baked response as parameter.
294 virtual void Start() OVERRIDE;
296 virtual const GURL& GetURL() const OVERRIDE;
298 virtual ~FakeURLFetcher();
301 // This is the method which actually calls the delegate that is passed in the
305 base::WeakPtrFactory<FakeURLFetcher> weak_factory_;
307 DISALLOW_COPY_AND_ASSIGN(FakeURLFetcher);
311 // FakeURLFetcherFactory is a factory for FakeURLFetcher objects. When
312 // instantiated, it sets itself up as the default URLFetcherFactory. Fake
313 // responses for given URLs can be set using SetFakeResponse.
315 // This class is not thread-safe. You should not call SetFakeResponse or
316 // ClearFakeResponse at the same time you call CreateURLFetcher. However, it is
317 // OK to start URLFetcher objects while setting or clearing fake responses
318 // since already created URLFetcher objects will not be affected by any changes
319 // made to the fake responses (once a URLFetcher object is created you cannot
320 // change its fake response).
323 // FakeURLFetcherFactory factory;
325 // // You know that class SomeService will request http://a.com/success and you
326 // // want to respond with a simple html page and an HTTP/200 code.
327 // factory.SetFakeResponse("http://a.com/success",
328 // "<html><body>hello world</body></html>",
330 // // You know that class SomeService will request url http://a.com/failure and
331 // // you want to test the service class by returning a server error.
332 // factory.SetFakeResponse("http://a.com/failure",
334 // HTTP_INTERNAL_SERVER_ERROR);
335 // // You know that class SomeService will request url http://a.com/error and
336 // // you want to test the service class by returning a specific error code,
337 // // say, a HTTP/401 error.
338 // factory.SetFakeResponse("http://a.com/error",
340 // HTTP_UNAUTHORIZED);
342 // SomeService service;
343 // service.Run(); // Will eventually request these three URLs.
344 class FakeURLFetcherFactory : public URLFetcherFactory,
345 public ScopedURLFetcherFactory {
347 // Parameters to FakeURLFetcherCreator: url, delegate, response_data,
349 // |url| URL for instantiated FakeURLFetcher
350 // |delegate| Delegate for FakeURLFetcher
351 // |response_data| response data for FakeURLFetcher
352 // |response_code| response code for FakeURLFetcher
353 // These arguments should by default be used in instantiating FakeURLFetcher
354 // as follows: new FakeURLFetcher(url, delegate, response_data, response_code)
355 typedef base::Callback<scoped_ptr<FakeURLFetcher>(
359 HttpStatusCode)> FakeURLFetcherCreator;
361 // |default_factory|, which can be NULL, is a URLFetcherFactory that
362 // will be used to construct a URLFetcher in case the URL being created
363 // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
364 // created in this case.
365 explicit FakeURLFetcherFactory(URLFetcherFactory* default_factory);
367 // |default_factory|, which can be NULL, is a URLFetcherFactory that
368 // will be used to construct a URLFetcher in case the URL being created
369 // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
370 // created in this case.
371 // |creator| is a callback that returns will be called to create a
372 // FakeURLFetcher if a response is found to a given URL. It can be
373 // set to MakeFakeURLFetcher.
374 FakeURLFetcherFactory(URLFetcherFactory* default_factory,
375 const FakeURLFetcherCreator& creator);
377 virtual ~FakeURLFetcherFactory();
379 // If no fake response is set for the given URL this method will delegate the
380 // call to |default_factory_| if it is not NULL, or return NULL if it is
382 // Otherwise, it will return a URLFetcher object which will respond with the
383 // pre-baked response that the client has set by calling SetFakeResponse().
384 virtual URLFetcher* CreateURLFetcher(
387 URLFetcher::RequestType request_type,
388 URLFetcherDelegate* d) OVERRIDE;
390 // Sets the fake response for a given URL. The |response_data| may be empty.
391 // The |response_code| may be any HttpStatusCode. For instance, HTTP_OK will
392 // return an HTTP/200 and HTTP_INTERNAL_SERVER_ERROR will return an HTTP/500.
393 // Note: The URLRequestStatus of FakeURLFetchers created by the factory will
394 // be FAILED for HttpStatusCodes HTTP/5xx, and SUCCESS for all other codes.
395 void SetFakeResponse(const GURL& url,
396 const std::string& response_data,
397 HttpStatusCode response_code);
399 // Clear all the fake responses that were previously set via
400 // SetFakeResponse().
401 void ClearFakeResponses();
404 const FakeURLFetcherCreator creator_;
405 typedef std::map<GURL,
406 std::pair<std::string, HttpStatusCode> > FakeResponseMap;
407 FakeResponseMap fake_responses_;
408 URLFetcherFactory* const default_factory_;
410 static scoped_ptr<FakeURLFetcher> DefaultFakeURLFetcherCreator(
412 URLFetcherDelegate* delegate,
413 const std::string& response_data,
414 HttpStatusCode response_code);
415 DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory);
418 // This is an implementation of URLFetcherFactory that will create a
419 // URLFetcherImpl. It can be use in conjunction with a FakeURLFetcherFactory in
420 // integration tests to control the behavior of some requests but execute
421 // all the other ones.
422 class URLFetcherImplFactory : public URLFetcherFactory {
424 URLFetcherImplFactory();
425 virtual ~URLFetcherImplFactory();
427 // This method will create a real URLFetcher.
428 virtual URLFetcher* CreateURLFetcher(
431 URLFetcher::RequestType request_type,
432 URLFetcherDelegate* d) OVERRIDE;
438 #endif // NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_