1// Copyright (c) 2010 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 CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_
6#define CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_
7#pragma once
8
9#include <list>
10#include <map>
11#include <string>
12#include <utility>
13
14#include "chrome/common/net/url_fetcher.h"
15#include "googleurl/src/gurl.h"
16
17// TestURLFetcher and TestURLFetcherFactory are used for testing consumers of
18// URLFetcher. TestURLFetcherFactory is a URLFetcher::Factory that creates
19// TestURLFetchers. TestURLFetcher::Start is overriden to do nothing. It is
20// expected that you'll grab the delegate from the TestURLFetcher and invoke
21// the callback method when appropriate. In this way it's easy to mock a
22// URLFetcher.
23// Typical usage:
24//   // TestURLFetcher requires a MessageLoop:
25//   MessageLoopForUI message_loop;
26//   // And io_thread to release URLRequestContextGetter in URLFetcher::Core.
27//   BrowserThread io_thread(BrowserThread::IO, &message_loop);
28//   // Create and register factory.
29//   TestURLFetcherFactory factory;
30//   URLFetcher::set_factory(&factory);
31//   // Do something that triggers creation of a URLFetcher.
32//   TestURLFetcher* fetcher = factory.GetFetcherByID(expected_id);
33//   DCHECK(fetcher);
34//   // Notify delegate with whatever data you want.
35//   fetcher->delegate()->OnURLFetchComplete(...);
36//   // Make sure consumer of URLFetcher does the right thing.
37//   ...
38//   // Reset factory.
39//   URLFetcher::set_factory(NULL);
40//
41// Note: if you don't know when your request objects will be created you
42// might want to use the FakeUrlFetcher and FakeUrlFetcherFactory classes
43// below.
44
45class TestURLFetcher : public URLFetcher {
46 public:
47  TestURLFetcher(int id,
48                 const GURL& url,
49                 RequestType request_type,
50                 Delegate* d);
51  ~TestURLFetcher();
52
53  // Overriden to do nothing. It is assumed the caller will notify the delegate.
54  virtual void Start() {}
55
56  // Overriden to cache the chunks uploaded. Caller can read back the uploaded
57  // chunks with the upload_data() accessor.
58  virtual void AppendChunkToUpload(const std::string& data, bool is_last_chunk);
59
60  // Unique ID in our factory.
61  int id() const { return id_; }
62
63  // URL we were created with. Because of how we're using URLFetcher url()
64  // always returns an empty URL. Chances are you'll want to use original_url()
65  // in your tests.
66  const GURL& original_url() const { return original_url_; }
67
68  // Returns the data uploaded on this URLFetcher.
69  const std::string& upload_data() const { return URLFetcher::upload_data(); }
70
71  // Returns the chunks of data uploaded on this URLFetcher.
72  const std::list<std::string>& upload_chunks() const { return chunks_; }
73
74  // Returns the delegate installed on the URLFetcher.
75  Delegate* delegate() const { return URLFetcher::delegate(); }
76
77 private:
78  const int id_;
79  const GURL original_url_;
80  std::list<std::string> chunks_;
81  bool did_receive_last_chunk_;
82
83  DISALLOW_COPY_AND_ASSIGN(TestURLFetcher);
84};
85
86// Simple URLFetcher::Factory method that creates TestURLFetchers. All fetchers
87// are registered in a map by the id passed to the create method.
88class TestURLFetcherFactory : public URLFetcher::Factory {
89 public:
90  TestURLFetcherFactory();
91  virtual ~TestURLFetcherFactory();
92
93  virtual URLFetcher* CreateURLFetcher(int id,
94                                       const GURL& url,
95                                       URLFetcher::RequestType request_type,
96                                       URLFetcher::Delegate* d);
97  TestURLFetcher* GetFetcherByID(int id) const;
98  void RemoveFetcherFromMap(int id);
99
100 private:
101  // Maps from id passed to create to the returned URLFetcher.
102  typedef std::map<int, TestURLFetcher*> Fetchers;
103  Fetchers fetchers_;
104
105  DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory);
106};
107
108// The FakeUrlFetcher and FakeUrlFetcherFactory classes are similar to the
109// ones above but don't require you to know when exactly the URLFetcher objects
110// will be created.
111//
112// These classes let you set pre-baked HTTP responses for particular URLs.
113// E.g., if the user requests http://a.com/ then respond with an HTTP/500.
114//
115// We assume that the thread that is calling Start() on the URLFetcher object
116// has a message loop running.
117//
118// This class is not thread-safe.  You should not call SetFakeResponse or
119// ClearFakeResponse at the same time you call CreateURLFetcher.  However, it is
120// OK to start URLFetcher objects while setting or clearning fake responses
121// since already created URLFetcher objects will not be affected by any changes
122// made to the fake responses (once a URLFetcher object is created you cannot
123// change its fake response).
124//
125// Example usage:
126//  FakeURLFetcherFactory factory;
127//  URLFetcher::set_factory(&factory);
128//
129//  // You know that class SomeService will request url http://a.com/ and you
130//  // want to test the service class by returning an error.
131//  factory.SetFakeResponse("http://a.com/", "", false);
132//  // But if the service requests http://b.com/asdf you want to respond with
133//  // a simple html page and an HTTP/200 code.
134//  factory.SetFakeResponse("http://b.com/asdf",
135//                          "<html><body>hello world</body></html>",
136//                          true);
137//
138//  SomeService service;
139//  service.Run();  // Will eventually request these two URLs.
140
141class FakeURLFetcherFactory : public URLFetcher::Factory {
142 public:
143  FakeURLFetcherFactory();
144  virtual ~FakeURLFetcherFactory();
145
146  // If no fake response is set for the given URL this method will return NULL.
147  // Otherwise, it will return a URLFetcher object which will respond with the
148  // pre-baked response that the client has set by calling SetFakeResponse().
149  virtual URLFetcher* CreateURLFetcher(int id,
150                                       const GURL& url,
151                                       URLFetcher::RequestType request_type,
152                                       URLFetcher::Delegate* d);
153
154  // Sets the fake response for a given URL.  If success is true we will serve
155  // an HTTP/200 and an HTTP/500 otherwise.  The |response_data| may be empty.
156  void SetFakeResponse(const std::string& url,
157                       const std::string& response_data,
158                       bool success);
159
160  // Clear all the fake responses that were previously set via
161  // SetFakeResponse().
162  void ClearFakeReponses();
163
164 private:
165  typedef std::map<GURL, std::pair<std::string, bool> > FakeResponseMap;
166  FakeResponseMap fake_responses_;
167
168  DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory);
169};
170
171#endif  // CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_
172