blob: 62c0efbc569d21a29879e57f82b8e73b127faa93 [file] [log] [blame]
David Ghandehari9e5b5872016-07-28 09:50:04 -07001// 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
20namespace 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).
24class 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
59class TestURLFetcherFactory;
60class 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
216typedef 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.
222class 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
284class 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.
326class 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_