diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-12 18:40:10 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-12 18:40:10 +0000 |
commit | f870252fda3d5724feeda33aeb6deaf502643a31 (patch) | |
tree | ac8b4391c15be1d0bb3af6def8cba95d0587caae /net/http | |
parent | 2c9be01dc74d1b0edff9c9288abcb66516083af0 (diff) | |
download | chromium_src-f870252fda3d5724feeda33aeb6deaf502643a31.zip chromium_src-f870252fda3d5724feeda33aeb6deaf502643a31.tar.gz chromium_src-f870252fda3d5724feeda33aeb6deaf502643a31.tar.bz2 |
Http Cache: Add a backend factory class so that the caller
has more control about the backend instantiation.
BUG=none
TEST=current unit tests.
Review URL: http://codereview.chromium.org/2000011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47050 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_cache.cc | 113 | ||||
-rw-r--r-- | net/http/http_cache.h | 100 | ||||
-rw-r--r-- | net/http/http_cache_unittest.cc | 357 |
3 files changed, 268 insertions, 302 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 08b9aa6..d6624be 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -33,6 +33,23 @@ namespace net { +int HttpCache::DefaultBackend::CreateBackend(disk_cache::Backend** backend, + CompletionCallback* callback) { + DCHECK_GE(max_bytes_, 0); + if (callback) + return disk_cache::CreateCacheBackend(type_, path_, max_bytes_, true, + thread_, backend, callback); + + // This is just old code needed to support synchronous cache creation. + // TODO(rvargas): Remove this once all callers provide a callback. + if (type_ == MEMORY_CACHE) { + *backend = disk_cache::CreateInMemoryCacheBackend(max_bytes_); + } else { + *backend = disk_cache::CreateCacheBackend(path_, true, max_bytes_, type_); + } + return (*backend ? OK : ERR_FAILED); +} + //----------------------------------------------------------------------------- HttpCache::ActiveEntry::ActiveEntry(disk_cache::Entry* e) @@ -215,78 +232,41 @@ void HttpCache::MetadataWriter::OnIOComplete(int result) { //----------------------------------------------------------------------------- HttpCache::HttpCache(NetworkChangeNotifier* network_change_notifier, - HostResolver* host_resolver, - ProxyService* proxy_service, + HostResolver* host_resolver, ProxyService* proxy_service, SSLConfigService* ssl_config_service, HttpAuthHandlerFactory* http_auth_handler_factory, - const FilePath& cache_dir, - MessageLoop* cache_thread, - int cache_size) - : disk_cache_dir_(cache_dir), - cache_thread_(cache_thread), + BackendFactory* backend_factory) + : backend_factory_(backend_factory), temp_backend_(NULL), building_backend_(false), mode_(NORMAL), - type_(DISK_CACHE), network_layer_(HttpNetworkLayer::CreateFactory( network_change_notifier, host_resolver, proxy_service, ssl_config_service, http_auth_handler_factory)), ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), - enable_range_support_(true), - cache_size_(cache_size), - create_backend_fn_(NULL) { + enable_range_support_(true) { } HttpCache::HttpCache(HttpNetworkSession* session, - const FilePath& cache_dir, - MessageLoop* cache_thread, - int cache_size) - : disk_cache_dir_(cache_dir), - cache_thread_(cache_thread), + BackendFactory* backend_factory) + : backend_factory_(backend_factory), temp_backend_(NULL), building_backend_(false), mode_(NORMAL), - type_(DISK_CACHE), network_layer_(HttpNetworkLayer::CreateFactory(session)), ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), - enable_range_support_(true), - cache_size_(cache_size), - create_backend_fn_(NULL) { -} - -HttpCache::HttpCache(NetworkChangeNotifier* network_change_notifier, - HostResolver* host_resolver, - ProxyService* proxy_service, - SSLConfigService* ssl_config_service, - HttpAuthHandlerFactory* http_auth_handler_factory, - int cache_size) - : cache_thread_(NULL), - temp_backend_(NULL), - building_backend_(false), - mode_(NORMAL), - type_(MEMORY_CACHE), - network_layer_(HttpNetworkLayer::CreateFactory( - network_change_notifier, host_resolver, proxy_service, - ssl_config_service, http_auth_handler_factory)), - ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), - enable_range_support_(true), - cache_size_(cache_size), - create_backend_fn_(NULL) { + enable_range_support_(true) { } HttpCache::HttpCache(HttpTransactionFactory* network_layer, - disk_cache::Backend* disk_cache) - : cache_thread_(NULL), + BackendFactory* backend_factory) + : backend_factory_(backend_factory), temp_backend_(NULL), building_backend_(false), mode_(NORMAL), - type_(DISK_CACHE), network_layer_(network_layer), - disk_cache_(disk_cache), ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), - enable_range_support_(true), - cache_size_(0), - create_backend_fn_(NULL) { + enable_range_support_(true) { } HttpCache::~HttpCache() { @@ -322,16 +302,11 @@ disk_cache::Backend* HttpCache::GetBackend() { if (disk_cache_.get()) return disk_cache_.get(); - DCHECK_GE(cache_size_, 0); - if (type_ == MEMORY_CACHE) { - // We may end up with no folder name and no cache if the initialization - // of the disk cache fails. We want to be sure that what we wanted to have - // was an in-memory cache. - disk_cache_.reset(disk_cache::CreateInMemoryCacheBackend(cache_size_)); - } else if (!disk_cache_dir_.empty()) { - disk_cache_.reset(disk_cache::CreateCacheBackend(disk_cache_dir_, true, - cache_size_, type_)); - disk_cache_dir_ = FilePath(); // Reclaim memory. + if (backend_factory_.get()) { + disk_cache::Backend* backend; + if (OK == backend_factory_->CreateBackend(&backend, NULL)) + disk_cache_.reset(backend); + backend_factory_.reset(); // Reclaim memory. } return disk_cache_.get(); } @@ -345,7 +320,6 @@ int HttpCache::GetBackend(disk_cache::Backend** backend, return OK; } - DCHECK_GE(cache_size_, 0); return CreateBackend(backend, callback); } @@ -445,12 +419,9 @@ void HttpCache::CloseCurrentConnections() { int HttpCache::CreateBackend(disk_cache::Backend** backend, CompletionCallback* callback) { - // We may end up with no folder name and no cache if the initialization - // of the disk cache fails. - if (type_ != MEMORY_CACHE && disk_cache_dir_.empty()) + if (!backend_factory_.get()) return ERR_FAILED; - DCHECK_GE(cache_size_, 0); building_backend_ = true; scoped_ptr<WorkItem> item(new WorkItem(WI_CREATE_BACKEND, NULL, callback, @@ -471,18 +442,7 @@ int HttpCache::CreateBackend(disk_cache::Backend** backend, BackendCallback* my_callback = new BackendCallback(this, pending_op); pending_op->callback = my_callback; - // See if this is a unit test. TODO(rvargas): Cleanup this after removing the - // overloaded method. - int rv; - if (create_backend_fn_) { - rv = create_backend_fn_(type_, disk_cache_dir_, cache_size_, true, - cache_thread_, &temp_backend_, my_callback); - } else { - rv = disk_cache::CreateCacheBackend(type_, disk_cache_dir_, cache_size_, - true, cache_thread_, &temp_backend_, - my_callback); - } - + int rv = backend_factory_->CreateBackend(&temp_backend_, my_callback); if (rv != ERR_IO_PENDING) { pending_op->writer->ClearCallback(); my_callback->Run(rv); @@ -1060,15 +1020,14 @@ void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) { WorkItemOperation op = item->operation(); DCHECK_EQ(WI_CREATE_BACKEND, op); - if (type_ != MEMORY_CACHE) - disk_cache_dir_ = FilePath(); // Reclaim memory. + backend_factory_.reset(); // Reclaim memory. if (result == OK) disk_cache_.reset(temp_backend_); item->DoCallback(result, temp_backend_); - // Notify and all callers and delete all pending work items. + // Notify all callers and delete all pending work items. while (!pending_op->pending_queue.empty()) { scoped_ptr<WorkItem> pending_item(pending_op->pending_queue.front()); pending_op->pending_queue.pop_front(); diff --git a/net/http/http_cache.h b/net/http/http_cache.h index bb2bf48..c82dc4e 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h @@ -26,7 +26,6 @@ #include "net/base/cache_type.h" #include "net/base/completion_callback.h" #include "net/http/http_transaction_factory.h" -#include "testing/gtest/include/gtest/gtest_prod.h" class GURL; class MessageLoop; @@ -68,45 +67,68 @@ class HttpCache : public HttpTransactionFactory, DISABLE }; - // Initialize the cache from the directory where its data is stored. The - // disk cache is initialized lazily (by CreateTransaction) in this case. If - // |cache_size| is zero, a default value will be calculated automatically. - // The |cache_thread| is the thread where disk operations should take place. + // A BackendFactory creates a backend object to be used by the HttpCache. + class BackendFactory { + public: + virtual ~BackendFactory() {} + + // The actual method to build the backend. Returns a net error code. If + // ERR_IO_PENDING is returned, the |callback| will be notified when the + // operation completes, and |backend| must remain valid until the + // notification arrives. + // The implementation must not access the factory object after invoking the + // |callback| because the object can be deleted from within the callback. + virtual int CreateBackend(disk_cache::Backend** backend, + CompletionCallback* callback) = 0; + }; + + // A default backend factory for the common use cases. + class DefaultBackend : public BackendFactory { + public: + // |path| is the destination for any files used by the backend, and + // |cache_thread| is the thread where disk operations should take place. If + // |max_bytes| is zero, a default value will be calculated automatically. + DefaultBackend(CacheType type, const FilePath& path, int max_bytes, + MessageLoop* thread) + : type_(type), path_(path), max_bytes_(max_bytes), thread_(thread) {} + + // Returns a factory for an in-memory cache. + static BackendFactory* InMemory(int max_bytes) { + return new DefaultBackend(MEMORY_CACHE, FilePath(), max_bytes, NULL); + } + + // BackendFactory implementation. + virtual int CreateBackend(disk_cache::Backend** backend, + CompletionCallback* callback); + + private: + CacheType type_; + const FilePath path_; + int max_bytes_; + MessageLoop* thread_; + }; + + // The disk cache is initialized lazily (by CreateTransaction) in this case. + // The HttpCache takes ownership of the |backend_factory|. HttpCache(NetworkChangeNotifier* network_change_notifier, - HostResolver* host_resolver, - ProxyService* proxy_service, + HostResolver* host_resolver, ProxyService* proxy_service, SSLConfigService* ssl_config_service, HttpAuthHandlerFactory* http_auth_handler_factory, - const FilePath& cache_dir, - MessageLoop* cache_thread, - int cache_size); + BackendFactory* backend_factory); - // Initialize the cache from the directory where its data is stored. The - // disk cache is initialized lazily (by CreateTransaction) in this case. If - // |cache_size| is zero, a default value will be calculated automatically. + // The disk cache is initialized lazily (by CreateTransaction) in this case. // Provide an existing HttpNetworkSession, the cache can construct a // network layer with a shared HttpNetworkSession in order for multiple - // network layers to share information (e.g. authenication data). - // The |cache_thread| is the thread where disk operations should take place. - HttpCache(HttpNetworkSession* session, const FilePath& cache_dir, - MessageLoop* cache_thread, int cache_size); - - // Initialize using an in-memory cache. The cache is initialized lazily - // (by CreateTransaction) in this case. If |cache_size| is zero, a default - // value will be calculated automatically. - HttpCache(NetworkChangeNotifier* network_change_notifier, - HostResolver* host_resolver, - ProxyService* proxy_service, - SSLConfigService* ssl_config_service, - HttpAuthHandlerFactory* http_auth_handler_factory, - int cache_size); + // network layers to share information (e.g. authenication data). The + // HttpCache takes ownership of the |backend_factory|. + HttpCache(HttpNetworkSession* session, BackendFactory* backend_factory); // Initialize the cache from its component parts, which is useful for - // testing. The lifetime of the network_layer and disk_cache are managed by - // the HttpCache and will be destroyed using |delete| when the HttpCache is + // testing. The lifetime of the network_layer and backend_factory are managed + // by the HttpCache and will be destroyed using |delete| when the HttpCache is // destroyed. HttpCache(HttpTransactionFactory* network_layer, - disk_cache::Backend* disk_cache); + BackendFactory* backend_factory); HttpTransactionFactory* network_layer() { return network_layer_.get(); } @@ -160,9 +182,6 @@ class HttpCache : public HttpTransactionFactory, void set_mode(Mode value) { mode_ = value; } Mode mode() { return mode_; } - void set_type(CacheType type) { type_ = type; } - CacheType type() { return type_; } - // Close currently active sockets so that fresh page loads will not use any // recycled connections. For sockets currently in use, they may not close // immediately, but they will not be reusable. This is for debugging. @@ -185,9 +204,6 @@ class HttpCache : public HttpTransactionFactory, friend class ::ViewCacheHelper; private: - FRIEND_TEST(HttpCacheTest, SimpleGET_WaitForBackend); - FRIEND_TEST(HttpCacheTest, SimpleGET_WaitForBackend_CancelCreate); - // Types -------------------------------------------------------------------- class BackendCallback; @@ -216,10 +232,6 @@ class HttpCache : public HttpTransactionFactory, typedef base::hash_map<std::string, PendingOp*> PendingOpsMap; typedef std::set<ActiveEntry*> ActiveEntriesSet; - typedef int (*CreateCacheBackendFn)(CacheType, const FilePath&, int, - bool, MessageLoop*, disk_cache::Backend**, - CompletionCallback*); - // Methods ------------------------------------------------------------------ // Creates the |backend| object and notifies the |callback| when the operation @@ -341,13 +353,11 @@ class HttpCache : public HttpTransactionFactory, // Variables ---------------------------------------------------------------- // Used when lazily constructing the disk_cache_. - FilePath disk_cache_dir_; - MessageLoop* cache_thread_; + scoped_ptr<BackendFactory> backend_factory_; disk_cache::Backend* temp_backend_; bool building_backend_; Mode mode_; - CacheType type_; scoped_ptr<HttpTransactionFactory> network_layer_; scoped_ptr<disk_cache::Backend> disk_cache_; @@ -364,14 +374,10 @@ class HttpCache : public HttpTransactionFactory, ScopedRunnableMethodFactory<HttpCache> task_factory_; bool enable_range_support_; - int cache_size_; typedef base::hash_map<std::string, int> PlaybackCacheMap; scoped_ptr<PlaybackCacheMap> playback_cache_map_; - // Used for unit tests. - CreateCacheBackendFn create_backend_fn_; - DISALLOW_COPY_AND_ASSIGN(HttpCache); }; diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 4508446..75fdc68 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -551,13 +551,23 @@ class MockDiskCache : public disk_cache::Backend { bool soft_failures_; }; +class MockBackendFactory : public net::HttpCache::BackendFactory { + public: + virtual int CreateBackend(disk_cache::Backend** backend, + net::CompletionCallback* callback) { + *backend = new MockDiskCache(); + return net::OK; + } +}; + class MockHttpCache { public: - MockHttpCache() : http_cache_(new MockNetworkLayer(), new MockDiskCache()) { + MockHttpCache() + : http_cache_(new MockNetworkLayer(), new MockBackendFactory()) { } - explicit MockHttpCache(disk_cache::Backend* disk_cache) - : http_cache_(new MockNetworkLayer(), disk_cache) { + explicit MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory) + : http_cache_(new MockNetworkLayer(), disk_cache_factory) { } net::HttpCache* http_cache() { return &http_cache_; } @@ -631,6 +641,58 @@ class MockDiskCacheNoCB : public MockDiskCache { } }; +class MockBackendNoCbFactory : public net::HttpCache::BackendFactory { + public: + virtual int CreateBackend(disk_cache::Backend** backend, + net::CompletionCallback* callback) { + *backend = new MockDiskCacheNoCB(); + return net::OK; + } +}; + +// This backend factory allows us to control the backend instantiation. +class MockBlockingBackendFactory : public net::HttpCache::BackendFactory { + public: + MockBlockingBackendFactory() + : backend_(NULL), callback_(NULL), block_(true), fail_(false) {} + + virtual int CreateBackend(disk_cache::Backend** backend, + net::CompletionCallback* callback) { + if (!block_) { + if (!fail_) + *backend = new MockDiskCache(); + return Result(); + } + + backend_ = backend; + callback_ = callback; + return net::ERR_IO_PENDING; + } + + // Completes the backend creation. Any blocked call will be notified via the + // provided callback. + void FinishCreation() { + block_ = false; + if (callback_) { + if (!fail_) + *backend_ = new MockDiskCache(); + net::CompletionCallback* cb = callback_; + callback_ = NULL; + cb->Run(Result()); // This object can be deleted here. + } + } + + void set_fail(bool fail) { fail_ = fail; } + + private: + int Result() { return fail_ ? net::ERR_FAILED : net::OK; } + + disk_cache::Backend** backend_; + net::CompletionCallback* callback_; + bool block_; + bool fail_; +}; + //----------------------------------------------------------------------------- // helpers @@ -929,169 +991,6 @@ struct Context { //----------------------------------------------------------------------------- // tests -namespace net { - -// This is a friend class of the HttpCache so that we can interact with it to -// perform a few internal tests. We override the backend factory method so that -// we can test the logic of backend instantiation. -class HttpCacheTest : public testing::Test { - public: - // Controls whether to block the backend instantiation or not. If |block| is - // true, any blocked call will be notified via the provided callback. - void BlockCacheCreation(bool block) { - block_ = block; - if (!block_ && callback_) { - *backend_ = new MockDiskCache(); - callback_->Run(OK); - callback_ = NULL; - } - } - - protected: - virtual void SetUp() { - current_test_ = this; - backend_ = NULL; - callback_ = NULL; - block_ = false; - } - - virtual void TearDown() { current_test_ = NULL; } - - // Implements disk_cache::CreateCacheBackend(). - static int MockCreateBackend(CacheType type, const FilePath& path, - int max_bytes, bool force, MessageLoop* thread, - disk_cache::Backend** backend, - CompletionCallback* callback) { - if (current_test_ == NULL) { - EXPECT_TRUE(current_test_); - return ERR_FAILED; - } - if (!current_test_->block_) { - *backend = new MockDiskCache(); - return OK; - } - - current_test_->backend_ = backend; - current_test_->callback_ = callback; - return ERR_IO_PENDING; - } - - private: - static HttpCacheTest* current_test_; - disk_cache::Backend** backend_; - CompletionCallback* callback_; - bool block_; -}; - -// Static. -HttpCacheTest* HttpCacheTest::current_test_ = NULL; - -// Tests that we queue requests when initializing the backend. -TEST_F(HttpCacheTest, SimpleGET_WaitForBackend) { - MockHttpCache cache(NULL); - cache.http_cache()->create_backend_fn_ = MockCreateBackend; - cache.http_cache()->set_type(MEMORY_CACHE); - BlockCacheCreation(true); - - MockHttpRequest request0(kSimpleGET_Transaction); - MockHttpRequest request1(kTypicalGET_Transaction); - MockHttpRequest request2(kETagGET_Transaction); - - std::vector<Context*> context_list; - const int kNumTransactions = 3; - - for (int i = 0; i < kNumTransactions; i++) { - context_list.push_back(new Context()); - Context* c = context_list[i]; - - c->result = cache.http_cache()->CreateTransaction(&c->trans); - EXPECT_EQ(OK, c->result); - } - - context_list[0]->result = context_list[0]->trans->Start( - &request0, &context_list[0]->callback, BoundNetLog()); - context_list[1]->result = context_list[1]->trans->Start( - &request1, &context_list[1]->callback, BoundNetLog()); - context_list[2]->result = context_list[2]->trans->Start( - &request2, &context_list[2]->callback, BoundNetLog()); - - // Just to make sure that everything is still pending. - MessageLoop::current()->RunAllPending(); - - // The first request should be creating the disk cache. - EXPECT_FALSE(context_list[0]->callback.have_result()); - - BlockCacheCreation(false); - - MessageLoop::current()->RunAllPending(); - EXPECT_EQ(3, cache.network_layer()->transaction_count()); - EXPECT_EQ(3, cache.disk_cache()->create_count()); - - for (int i = 0; i < kNumTransactions; ++i) { - EXPECT_TRUE(context_list[i]->callback.have_result()); - delete context_list[i]; - } -} - -// Tests that we can cancel requests that are queued waiting for the backend -// to be initialized. -TEST_F(HttpCacheTest, SimpleGET_WaitForBackend_CancelCreate) { - MockHttpCache cache(NULL); - cache.http_cache()->create_backend_fn_ = MockCreateBackend; - cache.http_cache()->set_type(MEMORY_CACHE); - BlockCacheCreation(true); - - MockHttpRequest request0(kSimpleGET_Transaction); - MockHttpRequest request1(kTypicalGET_Transaction); - MockHttpRequest request2(kETagGET_Transaction); - - std::vector<Context*> context_list; - const int kNumTransactions = 3; - - for (int i = 0; i < kNumTransactions; i++) { - context_list.push_back(new Context()); - Context* c = context_list[i]; - - c->result = cache.http_cache()->CreateTransaction(&c->trans); - EXPECT_EQ(OK, c->result); - } - - context_list[0]->result = context_list[0]->trans->Start( - &request0, &context_list[0]->callback, BoundNetLog()); - context_list[1]->result = context_list[1]->trans->Start( - &request1, &context_list[1]->callback, BoundNetLog()); - context_list[2]->result = context_list[2]->trans->Start( - &request2, &context_list[2]->callback, BoundNetLog()); - - // Just to make sure that everything is still pending. - MessageLoop::current()->RunAllPending(); - - // The first request should be creating the disk cache. - EXPECT_FALSE(context_list[0]->callback.have_result()); - - // Cancel a request from the pending queue. - delete context_list[1]; - context_list[1] = NULL; - - // Cancel the request that is creating the entry. - delete context_list[0]; - context_list[0] = NULL; - - // Complete the last transaction. - BlockCacheCreation(false); - - context_list[2]->result = - context_list[2]->callback.GetResult(context_list[2]->result); - ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction); - - EXPECT_EQ(1, cache.network_layer()->transaction_count()); - EXPECT_EQ(1, cache.disk_cache()->create_count()); - - delete context_list[2]; -} - -} // net namespace. - TEST(HttpCache, CreateThenDestroy) { MockHttpCache cache; @@ -1102,11 +1001,9 @@ TEST(HttpCache, CreateThenDestroy) { } TEST(HttpCache, GetBackend) { - // This will initialize a cache object with NULL backend. - MockHttpCache cache(NULL); + MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(0)); // This will lazily initialize the backend. - cache.http_cache()->set_type(net::MEMORY_CACHE); EXPECT_TRUE(cache.http_cache()->GetBackend()); } @@ -1155,7 +1052,10 @@ TEST(HttpCache, SimpleGETNoDiskCache) { TEST(HttpCache, SimpleGETNoDiskCache2) { // This will initialize a cache object with NULL backend. - MockHttpCache cache(NULL); + MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); + factory->set_fail(true); + factory->FinishCreation(); // We'll complete synchronously. + MockHttpCache cache(factory); // Read from the network, and don't use the cache. RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); @@ -1632,9 +1532,7 @@ TEST(HttpCache, SimpleGET_RacingReaders) { // See http://code.google.com/p/chromium/issues/detail?id=25588 TEST(HttpCache, SimpleGET_DoomWithPending) { // We need simultaneous doomed / not_doomed entries so let's use a real cache. - disk_cache::Backend* disk_cache = - disk_cache::CreateInMemoryCacheBackend(1024 * 1024); - MockHttpCache cache(disk_cache); + MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024)); MockHttpRequest request(kSimpleGET_Transaction); MockHttpRequest writer_request(kSimpleGET_Transaction); @@ -1919,7 +1817,8 @@ TEST(HttpCache, SimpleGET_AbandonedCacheRead) { // Tests that we can delete the HttpCache and deal with queued transactions // ("waiting for the backend" as opposed to Active or Doomed entries). TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) { - scoped_ptr<MockHttpCache> cache(new MockHttpCache(new MockDiskCacheNoCB())); + scoped_ptr<MockHttpCache> cache(new MockHttpCache( + new MockBackendNoCbFactory())); MockHttpRequest request(kSimpleGET_Transaction); @@ -1952,6 +1851,106 @@ TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) { } } +// Tests that we queue requests when initializing the backend. +TEST(HttpCache, SimpleGET_WaitForBackend) { + MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); + MockHttpCache cache(factory); + + MockHttpRequest request0(kSimpleGET_Transaction); + MockHttpRequest request1(kTypicalGET_Transaction); + MockHttpRequest request2(kETagGET_Transaction); + + std::vector<Context*> context_list; + const int kNumTransactions = 3; + + for (int i = 0; i < kNumTransactions; i++) { + context_list.push_back(new Context()); + Context* c = context_list[i]; + + c->result = cache.http_cache()->CreateTransaction(&c->trans); + EXPECT_EQ(net::OK, c->result); + } + + context_list[0]->result = context_list[0]->trans->Start( + &request0, &context_list[0]->callback, net::BoundNetLog()); + context_list[1]->result = context_list[1]->trans->Start( + &request1, &context_list[1]->callback, net::BoundNetLog()); + context_list[2]->result = context_list[2]->trans->Start( + &request2, &context_list[2]->callback, net::BoundNetLog()); + + // Just to make sure that everything is still pending. + MessageLoop::current()->RunAllPending(); + + // The first request should be creating the disk cache. + EXPECT_FALSE(context_list[0]->callback.have_result()); + + factory->FinishCreation(); + + MessageLoop::current()->RunAllPending(); + EXPECT_EQ(3, cache.network_layer()->transaction_count()); + EXPECT_EQ(3, cache.disk_cache()->create_count()); + + for (int i = 0; i < kNumTransactions; ++i) { + EXPECT_TRUE(context_list[i]->callback.have_result()); + delete context_list[i]; + } +} + +// Tests that we can cancel requests that are queued waiting for the backend +// to be initialized. +TEST(HttpCache, SimpleGET_WaitForBackend_CancelCreate) { + MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); + MockHttpCache cache(factory); + + MockHttpRequest request0(kSimpleGET_Transaction); + MockHttpRequest request1(kTypicalGET_Transaction); + MockHttpRequest request2(kETagGET_Transaction); + + std::vector<Context*> context_list; + const int kNumTransactions = 3; + + for (int i = 0; i < kNumTransactions; i++) { + context_list.push_back(new Context()); + Context* c = context_list[i]; + + c->result = cache.http_cache()->CreateTransaction(&c->trans); + EXPECT_EQ(net::OK, c->result); + } + + context_list[0]->result = context_list[0]->trans->Start( + &request0, &context_list[0]->callback, net::BoundNetLog()); + context_list[1]->result = context_list[1]->trans->Start( + &request1, &context_list[1]->callback, net::BoundNetLog()); + context_list[2]->result = context_list[2]->trans->Start( + &request2, &context_list[2]->callback, net::BoundNetLog()); + + // Just to make sure that everything is still pending. + MessageLoop::current()->RunAllPending(); + + // The first request should be creating the disk cache. + EXPECT_FALSE(context_list[0]->callback.have_result()); + + // Cancel a request from the pending queue. + delete context_list[1]; + context_list[1] = NULL; + + // Cancel the request that is creating the entry. + delete context_list[0]; + context_list[0] = NULL; + + // Complete the last transaction. + factory->FinishCreation(); + + context_list[2]->result = + context_list[2]->callback.GetResult(context_list[2]->result); + ReadAndVerifyTransaction(context_list[2]->trans.get(), kETagGET_Transaction); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + EXPECT_EQ(1, cache.disk_cache()->create_count()); + + delete context_list[2]; +} + TEST(HttpCache, TypicalGET_ConditionalRequest) { MockHttpCache cache; @@ -3546,9 +3545,7 @@ TEST(HttpCache, RangeGET_InvalidResponse3) { // Tests that we handle large range values properly. TEST(HttpCache, RangeGET_LargeValues) { // We need a real sparse cache for this test. - disk_cache::Backend* disk_cache = - disk_cache::CreateInMemoryCacheBackend(1024 * 1024); - MockHttpCache cache(disk_cache); + MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024)); cache.http_cache()->set_enable_range_support(true); std::string headers; @@ -3580,7 +3577,11 @@ TEST(HttpCache, RangeGET_LargeValues) { // Tests that we don't crash with a range request if the disk cache was not // initialized properly. TEST(HttpCache, RangeGET_NoDiskCache) { - MockHttpCache cache(NULL); + MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); + factory->set_fail(true); + factory->FinishCreation(); // We'll complete synchronously. + MockHttpCache cache(factory); + cache.http_cache()->set_enable_range_support(true); AddMockTransaction(&kRangeGET_TransactionOK); |