// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_ #define CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_ #pragma once #include <list> #include <map> #include <string> #include <utility> #include "chrome/common/net/url_fetcher.h" #include "googleurl/src/gurl.h" // TestURLFetcher and TestURLFetcherFactory are used for testing consumers of // URLFetcher. TestURLFetcherFactory is a URLFetcher::Factory that creates // TestURLFetchers. TestURLFetcher::Start is overriden to do nothing. It is // expected that you'll grab the delegate from the TestURLFetcher and invoke // the callback method when appropriate. In this way it's easy to mock a // URLFetcher. // Typical usage: // // TestURLFetcher requires a MessageLoop: // MessageLoopForUI message_loop; // // And io_thread to release URLRequestContextGetter in URLFetcher::Core. // BrowserThread io_thread(BrowserThread::IO, &message_loop); // // Create and register factory. // TestURLFetcherFactory factory; // URLFetcher::set_factory(&factory); // // Do something that triggers creation of a URLFetcher. // TestURLFetcher* fetcher = factory.GetFetcherByID(expected_id); // DCHECK(fetcher); // // Notify delegate with whatever data you want. // fetcher->delegate()->OnURLFetchComplete(...); // // Make sure consumer of URLFetcher does the right thing. // ... // // Reset factory. // URLFetcher::set_factory(NULL); // // Note: if you don't know when your request objects will be created you // might want to use the FakeUrlFetcher and FakeUrlFetcherFactory classes // below. class TestURLFetcher : public URLFetcher { public: TestURLFetcher(int id, const GURL& url, RequestType request_type, Delegate* d); ~TestURLFetcher(); // Overriden to do nothing. It is assumed the caller will notify the delegate. virtual void Start() {} // Overriden to cache the chunks uploaded. Caller can read back the uploaded // chunks with the upload_data() accessor. virtual void AppendChunkToUpload(const std::string& data, bool is_last_chunk); // Unique ID in our factory. int id() const { return id_; } // URL we were created with. Because of how we're using URLFetcher url() // always returns an empty URL. Chances are you'll want to use original_url() // in your tests. const GURL& original_url() const { return original_url_; } // Returns the data uploaded on this URLFetcher. const std::string& upload_data() const { return URLFetcher::upload_data(); } // Returns the chunks of data uploaded on this URLFetcher. const std::list<std::string>& upload_chunks() const { return chunks_; } // Returns the delegate installed on the URLFetcher. Delegate* delegate() const { return URLFetcher::delegate(); } private: const int id_; const GURL original_url_; std::list<std::string> chunks_; bool did_receive_last_chunk_; DISALLOW_COPY_AND_ASSIGN(TestURLFetcher); }; // Simple URLFetcher::Factory method that creates TestURLFetchers. All fetchers // are registered in a map by the id passed to the create method. class TestURLFetcherFactory : public URLFetcher::Factory { public: TestURLFetcherFactory(); virtual ~TestURLFetcherFactory(); virtual URLFetcher* CreateURLFetcher(int id, const GURL& url, URLFetcher::RequestType request_type, URLFetcher::Delegate* d); TestURLFetcher* GetFetcherByID(int id) const; void RemoveFetcherFromMap(int id); private: // Maps from id passed to create to the returned URLFetcher. typedef std::map<int, TestURLFetcher*> Fetchers; Fetchers fetchers_; DISALLOW_COPY_AND_ASSIGN(TestURLFetcherFactory); }; // The FakeUrlFetcher and FakeUrlFetcherFactory classes are similar to the // ones above but don't require you to know when exactly the URLFetcher objects // will be created. // // These classes let you set pre-baked HTTP responses for particular URLs. // E.g., if the user requests http://a.com/ then respond with an HTTP/500. // // We assume that the thread that is calling Start() on the URLFetcher object // has a message loop running. // // This class is not thread-safe. You should not call SetFakeResponse or // ClearFakeResponse at the same time you call CreateURLFetcher. However, it is // OK to start URLFetcher objects while setting or clearning fake responses // since already created URLFetcher objects will not be affected by any changes // made to the fake responses (once a URLFetcher object is created you cannot // change its fake response). // // Example usage: // FakeURLFetcherFactory factory; // URLFetcher::set_factory(&factory); // // // You know that class SomeService will request url http://a.com/ and you // // want to test the service class by returning an error. // factory.SetFakeResponse("http://a.com/", "", false); // // But if the service requests http://b.com/asdf you want to respond with // // a simple html page and an HTTP/200 code. // factory.SetFakeResponse("http://b.com/asdf", // "<html><body>hello world</body></html>", // true); // // SomeService service; // service.Run(); // Will eventually request these two URLs. class FakeURLFetcherFactory : public URLFetcher::Factory { public: FakeURLFetcherFactory(); virtual ~FakeURLFetcherFactory(); // If no fake response is set for the given URL this method will return NULL. // Otherwise, it will return a URLFetcher object which will respond with the // pre-baked response that the client has set by calling SetFakeResponse(). virtual URLFetcher* CreateURLFetcher(int id, const GURL& url, URLFetcher::RequestType request_type, URLFetcher::Delegate* d); // Sets the fake response for a given URL. If success is true we will serve // an HTTP/200 and an HTTP/500 otherwise. The |response_data| may be empty. void SetFakeResponse(const std::string& url, const std::string& response_data, bool success); // Clear all the fake responses that were previously set via // SetFakeResponse(). void ClearFakeReponses(); private: typedef std::map<GURL, std::pair<std::string, bool> > FakeResponseMap; FakeResponseMap fake_responses_; DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory); }; #endif // CHROME_COMMON_NET_TEST_URL_FETCHER_FACTORY_H_