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 SetReferrerPolicy(
108 URLRequest::ReferrerPolicy referrer_policy
) override
;
109 virtual void SetExtraRequestHeaders(
110 const std::string
& extra_request_headers
) override
;
111 virtual void AddExtraRequestHeader(const std::string
& header_line
) 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::SequencedTaskRunner
> file_task_runner
) override
;
128 virtual void SaveResponseToTemporaryFile(
129 scoped_refptr
<base::SequencedTaskRunner
> 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 void GetExtraRequestHeaders(HttpRequestHeaders
* headers
) const;
154 // Sets owner of this class. Set it to a non-NULL value if you want
155 // to automatically unregister this fetcher from the owning factory
157 void set_owner(TestURLFetcherFactory
* owner
) { owner_
= owner
; }
159 // Unique ID in our factory.
160 int id() const { return id_
; }
162 // Returns the data uploaded on this URLFetcher.
163 const std::string
& upload_content_type() const {
164 return upload_content_type_
;
166 const std::string
& upload_data() const { return upload_data_
; }
167 const base::FilePath
& upload_file_path() const { return upload_file_path_
; }
169 // Returns the chunks of data uploaded on this URLFetcher.
170 const std::list
<std::string
>& upload_chunks() const { return chunks_
; }
172 // Checks whether the last call to |AppendChunkToUpload(...)| was final.
173 bool did_receive_last_chunk() const { return did_receive_last_chunk_
; }
175 // Returns the delegate installed on the URLFetcher.
176 URLFetcherDelegate
* delegate() const { return delegate_
; }
178 void set_url(const GURL
& url
) { fake_url_
= url
; }
179 void set_status(const URLRequestStatus
& status
);
180 void set_response_code(int response_code
) {
181 fake_response_code_
= response_code
;
183 void set_cookies(const ResponseCookies
& c
) { fake_cookies_
= c
; }
184 void set_was_fetched_via_proxy(bool flag
);
185 void set_response_headers(scoped_refptr
<HttpResponseHeaders
> headers
);
186 void set_backoff_delay(base::TimeDelta backoff_delay
);
187 void SetDelegateForTests(DelegateForTests
* delegate_for_tests
);
190 void SetResponseString(const std::string
& response
);
193 void SetResponseFilePath(const base::FilePath
& path
);
196 enum ResponseDestinationType
{
197 STRING
, // Default: In a std::string
198 TEMP_FILE
// Write to a temp file
201 TestURLFetcherFactory
* owner_
;
203 const GURL original_url_
;
204 URLFetcherDelegate
* delegate_
;
205 DelegateForTests
* delegate_for_tests_
;
206 std::string upload_content_type_
;
207 std::string upload_data_
;
208 base::FilePath upload_file_path_
;
209 std::list
<std::string
> chunks_
;
210 bool did_receive_last_chunk_
;
212 // User can use set_* methods to provide values returned by getters.
213 // Setting the real values is not possible, because the real class
214 // has no setters. The data is a private member of a class defined
215 // in a .cc file, so we can't get at it with friendship.
216 int fake_load_flags_
;
218 URLRequestStatus fake_status_
;
219 int fake_response_code_
;
220 ResponseCookies fake_cookies_
;
221 ResponseDestinationType fake_response_destination_
;
222 std::string fake_response_string_
;
223 base::FilePath fake_response_file_path_
;
224 bool fake_was_fetched_via_proxy_
;
225 scoped_refptr
<HttpResponseHeaders
> fake_response_headers_
;
226 HttpRequestHeaders fake_extra_request_headers_
;
227 int fake_max_retries_
;
228 base::TimeDelta fake_backoff_delay_
;
229 scoped_ptr
<URLFetcherResponseWriter
> response_writer_
;
231 DISALLOW_COPY_AND_ASSIGN(TestURLFetcher
);
234 typedef TestURLFetcher::DelegateForTests TestURLFetcherDelegateForTests
;
236 // Simple URLFetcherFactory method that creates TestURLFetchers. All fetchers
237 // are registered in a map by the id passed to the create method.
238 // Optionally, a fetcher may be automatically unregistered from the map upon
240 class TestURLFetcherFactory
: public URLFetcherFactory
,
241 public ScopedURLFetcherFactory
{
243 TestURLFetcherFactory();
244 virtual ~TestURLFetcherFactory();
246 virtual URLFetcher
* CreateURLFetcher(
249 URLFetcher::RequestType request_type
,
250 URLFetcherDelegate
* d
) override
;
251 TestURLFetcher
* GetFetcherByID(int id
) const;
252 void RemoveFetcherFromMap(int id
);
253 void SetDelegateForTests(TestURLFetcherDelegateForTests
* delegate_for_tests
);
254 void set_remove_fetcher_on_delete(bool remove_fetcher_on_delete
) {
255 remove_fetcher_on_delete_
= remove_fetcher_on_delete
;
259 // Maps from id passed to create to the returned URLFetcher.
260 typedef std::map
<int, TestURLFetcher
*> Fetchers
;
262 TestURLFetcherDelegateForTests
* delegate_for_tests_
;
263 // Whether to automatically unregister a fetcher from this factory upon its
264 // destruction, false by default.
265 bool remove_fetcher_on_delete_
;
267 DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory
);
270 // The FakeURLFetcher and FakeURLFetcherFactory classes are similar to the
271 // ones above but don't require you to know when exactly the URLFetcher objects
274 // These classes let you set pre-baked HTTP responses for particular URLs.
275 // E.g., if the user requests http://a.com/ then respond with an HTTP/500.
277 // We assume that the thread that is calling Start() on the URLFetcher object
278 // has a message loop running.
280 // FakeURLFetcher can be used to create a URLFetcher that will emit a fake
281 // response when started. This class can be used in place of an actual
285 // FakeURLFetcher fake_fetcher("http://a.com", some_delegate,
286 // "<html><body>hello world</body></html>",
289 // // Will schedule a call to some_delegate->OnURLFetchComplete(&fake_fetcher).
290 // fake_fetcher.Start();
291 class FakeURLFetcher
: public TestURLFetcher
{
293 // Normal URL fetcher constructor but also takes in a pre-baked response.
294 FakeURLFetcher(const GURL
& url
,
295 URLFetcherDelegate
* d
,
296 const std::string
& response_data
,
297 HttpStatusCode response_code
,
298 URLRequestStatus::Status status
);
300 // Start the request. This will call the given delegate asynchronously
301 // with the pre-baked response as parameter.
302 virtual void Start() override
;
304 virtual const GURL
& GetURL() const override
;
306 virtual ~FakeURLFetcher();
309 // This is the method which actually calls the delegate that is passed in the
313 base::WeakPtrFactory
<FakeURLFetcher
> weak_factory_
;
315 DISALLOW_COPY_AND_ASSIGN(FakeURLFetcher
);
319 // FakeURLFetcherFactory is a factory for FakeURLFetcher objects. When
320 // instantiated, it sets itself up as the default URLFetcherFactory. Fake
321 // responses for given URLs can be set using SetFakeResponse.
323 // This class is not thread-safe. You should not call SetFakeResponse or
324 // ClearFakeResponse at the same time you call CreateURLFetcher. However, it is
325 // OK to start URLFetcher objects while setting or clearing fake responses
326 // since already created URLFetcher objects will not be affected by any changes
327 // made to the fake responses (once a URLFetcher object is created you cannot
328 // change its fake response).
331 // FakeURLFetcherFactory factory;
333 // // You know that class SomeService will request http://a.com/success and you
334 // // want to respond with a simple html page and an HTTP/200 code.
335 // factory.SetFakeResponse("http://a.com/success",
336 // "<html><body>hello world</body></html>",
338 // URLRequestStatus::SUCCESS);
339 // // You know that class SomeService will request url http://a.com/servererror
340 // // and you want to test the service class by returning a server error.
341 // factory.SetFakeResponse("http://a.com/servererror",
343 // HTTP_INTERNAL_SERVER_ERROR,
344 // URLRequestStatus::SUCCESS);
345 // // You know that class SomeService will request url http://a.com/autherror
346 // // and you want to test the service class by returning a specific error
347 // // code, say, a HTTP/401 error.
348 // factory.SetFakeResponse("http://a.com/autherror",
350 // HTTP_UNAUTHORIZED,
351 // URLRequestStatus::SUCCESS);
353 // // You know that class SomeService will request url http://a.com/failure
354 // // and you want to test the service class by returning a failure in the
356 // factory.SetFakeResponse("http://a.com/failure",
358 // HTTP_INTERNAL_SERVER_ERROR,
359 // URLRequestStatus::FAILURE);
361 // SomeService service;
362 // service.Run(); // Will eventually request these three URLs.
363 class FakeURLFetcherFactory
: public URLFetcherFactory
,
364 public ScopedURLFetcherFactory
{
366 // Parameters to FakeURLFetcherCreator: url, delegate, response_data,
368 // |url| URL for instantiated FakeURLFetcher
369 // |delegate| Delegate for FakeURLFetcher
370 // |response_data| response data for FakeURLFetcher
371 // |response_code| response code for FakeURLFetcher
372 // |status| URL fetch status for FakeURLFetcher
373 // These arguments should by default be used in instantiating FakeURLFetcher
375 // new FakeURLFetcher(url, delegate, response_data, response_code, status)
376 typedef base::Callback
<scoped_ptr
<FakeURLFetcher
>(
381 URLRequestStatus::Status
)> FakeURLFetcherCreator
;
383 // |default_factory|, which can be NULL, is a URLFetcherFactory that
384 // will be used to construct a URLFetcher in case the URL being created
385 // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
386 // created in this case.
387 explicit FakeURLFetcherFactory(URLFetcherFactory
* default_factory
);
389 // |default_factory|, which can be NULL, is a URLFetcherFactory that
390 // will be used to construct a URLFetcher in case the URL being created
391 // has no pre-baked response. If it is NULL, a URLFetcherImpl will be
392 // created in this case.
393 // |creator| is a callback that returns will be called to create a
394 // FakeURLFetcher if a response is found to a given URL. It can be
395 // set to MakeFakeURLFetcher.
396 FakeURLFetcherFactory(URLFetcherFactory
* default_factory
,
397 const FakeURLFetcherCreator
& creator
);
399 virtual ~FakeURLFetcherFactory();
401 // If no fake response is set for the given URL this method will delegate the
402 // call to |default_factory_| if it is not NULL, or return NULL if it is
404 // Otherwise, it will return a URLFetcher object which will respond with the
405 // pre-baked response that the client has set by calling SetFakeResponse().
406 virtual URLFetcher
* CreateURLFetcher(
409 URLFetcher::RequestType request_type
,
410 URLFetcherDelegate
* d
) override
;
412 // Sets the fake response for a given URL. The |response_data| may be empty.
413 // The |response_code| may be any HttpStatusCode. For instance, HTTP_OK will
414 // return an HTTP/200 and HTTP_INTERNAL_SERVER_ERROR will return an HTTP/500.
415 // The |status| argument may be any URLRequestStatus::Status value. Typically,
416 // requests that return a valid HttpStatusCode have the SUCCESS status, while
417 // requests that indicate a failure to connect to the server have the FAILED
419 void SetFakeResponse(const GURL
& url
,
420 const std::string
& response_data
,
421 HttpStatusCode response_code
,
422 URLRequestStatus::Status status
);
424 // Clear all the fake responses that were previously set via
425 // SetFakeResponse().
426 void ClearFakeResponses();
429 struct FakeURLResponse
{
430 std::string response_data
;
431 HttpStatusCode response_code
;
432 URLRequestStatus::Status status
;
434 typedef std::map
<GURL
, FakeURLResponse
> FakeResponseMap
;
436 const FakeURLFetcherCreator creator_
;
437 FakeResponseMap fake_responses_
;
438 URLFetcherFactory
* const default_factory_
;
440 static scoped_ptr
<FakeURLFetcher
> DefaultFakeURLFetcherCreator(
442 URLFetcherDelegate
* delegate
,
443 const std::string
& response_data
,
444 HttpStatusCode response_code
,
445 URLRequestStatus::Status status
);
446 DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory
);
449 // This is an implementation of URLFetcherFactory that will create a
450 // URLFetcherImpl. It can be use in conjunction with a FakeURLFetcherFactory in
451 // integration tests to control the behavior of some requests but execute
452 // all the other ones.
453 class URLFetcherImplFactory
: public URLFetcherFactory
{
455 URLFetcherImplFactory();
456 virtual ~URLFetcherImplFactory();
458 // This method will create a real URLFetcher.
459 virtual URLFetcher
* CreateURLFetcher(
462 URLFetcher::RequestType request_type
,
463 URLFetcherDelegate
* d
) override
;
468 #endif // NET_URL_REQUEST_TEST_URL_FETCHER_FACTORY_H_