diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-22 21:19:08 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-22 21:19:08 +0000 |
commit | f4015600c484053dad1043fc974c57ef2e8dbff9 (patch) | |
tree | bdd6f55f78aff38bc228f64acbbdd693b52a8a06 /net | |
parent | 2d024be84200467d50ba6e26938473e75d6f000f (diff) | |
download | chromium_src-f4015600c484053dad1043fc974c57ef2e8dbff9.zip chromium_src-f4015600c484053dad1043fc974c57ef2e8dbff9.tar.gz chromium_src-f4015600c484053dad1043fc974c57ef2e8dbff9.tar.bz2 |
Split DiskCacheBasedSSLHostInfo unit tests to its own
file. I'll be adding more unit tests so it's a good time
to do this.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/8588011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111217 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/disk_cache_based_ssl_host_info_unittest.cc | 44 | ||||
-rw-r--r-- | net/http/http_cache_unittest.cc | 707 | ||||
-rw-r--r-- | net/http/mock_http_cache.cc | 613 | ||||
-rw-r--r-- | net/http/mock_http_cache.h | 233 | ||||
-rw-r--r-- | net/net.gyp | 3 |
5 files changed, 897 insertions, 703 deletions
diff --git a/net/http/disk_cache_based_ssl_host_info_unittest.cc b/net/http/disk_cache_based_ssl_host_info_unittest.cc new file mode 100644 index 0000000..d15548f --- /dev/null +++ b/net/http/disk_cache_based_ssl_host_info_unittest.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2011 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. + +#include "net/base/net_errors.h" +#include "net/base/ssl_config_service.h" +#include "net/http/disk_cache_based_ssl_host_info.h" +#include "net/http/mock_http_cache.h" +#include "testing/gtest/include/gtest/gtest.h" + +class DeleteSSLHostInfoOldCompletionCallback : public TestOldCompletionCallback { + public: + explicit DeleteSSLHostInfoOldCompletionCallback(net::SSLHostInfo* ssl_host_info) + : ssl_host_info_(ssl_host_info) {} + + virtual void RunWithParams(const Tuple1<int>& params) { + delete ssl_host_info_; + TestOldCompletionCallback::RunWithParams(params); + } + + private: + net::SSLHostInfo* ssl_host_info_; +}; + +// Tests that we can delete a DiskCacheBasedSSLHostInfo object in a +// completion callback for DiskCacheBasedSSLHostInfo::WaitForDataReady. +TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) { + net::CertVerifier cert_verifier; + // Use the blocking mock backend factory to force asynchronous completion + // of ssl_host_info->WaitForDataReady(), so that the callback will run. + MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); + MockHttpCache cache(factory); + net::SSLConfig ssl_config; + net::SSLHostInfo* ssl_host_info = + new net::DiskCacheBasedSSLHostInfo("https://www.verisign.com", ssl_config, + &cert_verifier, cache.http_cache()); + ssl_host_info->Start(); + DeleteSSLHostInfoOldCompletionCallback callback(ssl_host_info); + int rv = ssl_host_info->WaitForDataReady(&callback); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + // Now complete the backend creation and let the callback run. + factory->FinishCreation(); + EXPECT_EQ(net::OK, callback.GetResult(rv)); +} diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 9a07411..0c0ff6f 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -5,7 +5,6 @@ #include "net/http/http_cache.h" #include "base/bind.h" -#include "base/hash_tables.h" #include "base/memory/scoped_vector.h" #include "base/message_loop.h" #include "base/string_util.h" @@ -17,9 +16,7 @@ #include "net/base/net_errors.h" #include "net/base/net_log_unittest.h" #include "net/base/ssl_cert_request_info.h" -#include "net/base/ssl_config_service.h" #include "net/disk_cache/disk_cache.h" -#include "net/http/disk_cache_based_ssl_host_info.h" #include "net/http/http_byte_range.h" #include "net/http/http_request_headers.h" #include "net/http/http_request_info.h" @@ -28,671 +25,13 @@ #include "net/http/http_transaction.h" #include "net/http/http_transaction_unittest.h" #include "net/http/http_util.h" +#include "net/http/mock_http_cache.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; namespace { -int GetTestModeForEntry(const std::string& key) { - // 'key' is prefixed with an identifier if it corresponds to a cached POST. - // Skip past that to locate the actual URL. - // - // TODO(darin): It breaks the abstraction a bit that we assume 'key' is an - // URL corresponding to a registered MockTransaction. It would be good to - // have another way to access the test_mode. - GURL url; - if (isdigit(key[0])) { - size_t slash = key.find('/'); - DCHECK(slash != std::string::npos); - url = GURL(key.substr(slash + 1)); - } else { - url = GURL(key); - } - const MockTransaction* t = FindMockTransaction(url); - DCHECK(t); - return t->test_mode; -} - -// We can override the test mode for a given operation by setting this global -// variable. Just remember to reset it after the test!. -int g_test_mode = 0; - -// Returns the test mode after considering the global override. -int GetEffectiveTestMode(int test_mode) { - if (!g_test_mode) - return test_mode; - - return g_test_mode; -} - -//----------------------------------------------------------------------------- -// mock disk cache (a very basic memory cache implementation) - -static const int kNumCacheEntryDataIndices = 3; - -class MockDiskEntry : public disk_cache::Entry, - public base::RefCounted<MockDiskEntry> { - public: - MockDiskEntry() - : test_mode_(0), doomed_(false), sparse_(false), - fail_requests_(false), busy_(false), delayed_(false) { - } - - explicit MockDiskEntry(const std::string& key) - : key_(key), doomed_(false), sparse_(false), - fail_requests_(false), busy_(false), delayed_(false) { - test_mode_ = GetTestModeForEntry(key); - } - - bool is_doomed() const { return doomed_; } - - virtual void Doom() { - doomed_ = true; - } - - virtual void Close() { - Release(); - } - - virtual std::string GetKey() const { - if (fail_requests_) - return std::string(); - return key_; - } - - virtual Time GetLastUsed() const { - return Time::FromInternalValue(0); - } - - virtual Time GetLastModified() const { - return Time::FromInternalValue(0); - } - - virtual int32 GetDataSize(int index) const { - DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); - return static_cast<int32>(data_[index].size()); - } - - virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len, - net::OldCompletionCallback* callback) { - DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); - DCHECK(callback); - - if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; - - if (offset < 0 || offset > static_cast<int>(data_[index].size())) - return net::ERR_FAILED; - if (static_cast<size_t>(offset) == data_[index].size()) - return 0; - - int num = std::min(buf_len, static_cast<int>(data_[index].size()) - offset); - memcpy(buf->data(), &data_[index][offset], num); - - if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) - return num; - - CallbackLater(callback, num); - return net::ERR_IO_PENDING; - } - - virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, - net::OldCompletionCallback* callback, bool truncate) { - DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); - DCHECK(callback); - DCHECK(truncate); - - if (fail_requests_) { - CallbackLater(callback, net::ERR_CACHE_READ_FAILURE); - return net::ERR_IO_PENDING; - } - - if (offset < 0 || offset > static_cast<int>(data_[index].size())) - return net::ERR_FAILED; - - data_[index].resize(offset + buf_len); - if (buf_len) - memcpy(&data_[index][offset], buf->data(), buf_len); - - if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) - return buf_len; - - CallbackLater(callback, buf_len); - return net::ERR_IO_PENDING; - } - - virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, - net::OldCompletionCallback* callback) { - DCHECK(callback); - if (!sparse_ || busy_) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; - if (offset < 0) - return net::ERR_FAILED; - - if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; - - DCHECK(offset < kint32max); - int real_offset = static_cast<int>(offset); - if (!buf_len) - return 0; - - int num = std::min(static_cast<int>(data_[1].size()) - real_offset, - buf_len); - memcpy(buf->data(), &data_[1][real_offset], num); - - if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) - return num; - - CallbackLater(callback, num); - busy_ = true; - delayed_ = false; - return net::ERR_IO_PENDING; - } - - virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, - net::OldCompletionCallback* callback) { - DCHECK(callback); - if (busy_) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; - if (!sparse_) { - if (data_[1].size()) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; - sparse_ = true; - } - if (offset < 0) - return net::ERR_FAILED; - if (!buf_len) - return 0; - - if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; - - DCHECK(offset < kint32max); - int real_offset = static_cast<int>(offset); - - if (static_cast<int>(data_[1].size()) < real_offset + buf_len) - data_[1].resize(real_offset + buf_len); - - memcpy(&data_[1][real_offset], buf->data(), buf_len); - if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) - return buf_len; - - CallbackLater(callback, buf_len); - return net::ERR_IO_PENDING; - } - - virtual int GetAvailableRange(int64 offset, int len, int64* start, - net::OldCompletionCallback* callback) { - DCHECK(callback); - if (!sparse_ || busy_) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; - if (offset < 0) - return net::ERR_FAILED; - - if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; - - *start = offset; - DCHECK(offset < kint32max); - int real_offset = static_cast<int>(offset); - if (static_cast<int>(data_[1].size()) < real_offset) - return 0; - - int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len); - int count = 0; - for (; num > 0; num--, real_offset++) { - if (!count) { - if (data_[1][real_offset]) { - count++; - *start = real_offset; - } - } else { - if (!data_[1][real_offset]) - break; - count++; - } - } - if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) - return count; - - CallbackLater(callback, count); - return net::ERR_IO_PENDING; - } - - virtual bool CouldBeSparse() const { - return sparse_; - } - - virtual void CancelSparseIO() { cancel_ = true; } - - virtual int ReadyForSparseIO(net::OldCompletionCallback* completion_callback) { - if (!cancel_) - return net::OK; - - cancel_ = false; - DCHECK(completion_callback); - if (GetEffectiveTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) - return net::OK; - - // The pending operation is already in the message loop (and hopefuly - // already in the second pass). Just notify the caller that it finished. - CallbackLater(completion_callback, 0); - return net::ERR_IO_PENDING; - } - - // Fail most subsequent requests. - void set_fail_requests() { fail_requests_ = true; } - - // If |value| is true, don't deliver any completion callbacks until called - // again with |value| set to false. Caution: remember to enable callbacks - // again or all subsequent tests will fail. - static void IgnoreCallbacks(bool value) { - if (ignore_callbacks_ == value) - return; - ignore_callbacks_ = value; - if (!value) - StoreAndDeliverCallbacks(false, NULL, NULL, 0); - } - - private: - friend class base::RefCounted<MockDiskEntry>; - - struct CallbackInfo { - scoped_refptr<MockDiskEntry> entry; - net::OldCompletionCallback* callback; - int result; - }; - - ~MockDiskEntry() {} - - // Unlike the callbacks for MockHttpTransaction, we want this one to run even - // if the consumer called Close on the MockDiskEntry. We achieve that by - // leveraging the fact that this class is reference counted. - void CallbackLater(net::OldCompletionCallback* callback, int result) { - if (ignore_callbacks_) - return StoreAndDeliverCallbacks(true, this, callback, result); - MessageLoop::current()->PostTask(FROM_HERE, base::Bind( - &MockDiskEntry::RunCallback, this, callback, result)); - } - void RunCallback(net::OldCompletionCallback* callback, int result) { - if (busy_) { - // This is kind of hacky, but controlling the behavior of just this entry - // from a test is sort of complicated. What we really want to do is - // delay the delivery of a sparse IO operation a little more so that the - // request start operation (async) will finish without seeing the end of - // this operation (already posted to the message loop)... and without - // just delaying for n mS (which may cause trouble with slow bots). So - // we re-post this operation (all async sparse IO operations will take two - // trips trhough the message loop instead of one). - if (!delayed_) { - delayed_ = true; - return CallbackLater(callback, result); - } - } - busy_ = false; - callback->Run(result); - } - - // When |store| is true, stores the callback to be delivered later; otherwise - // delivers any callback previously stored. - static void StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry, - net::OldCompletionCallback* callback, - int result) { - static std::vector<CallbackInfo> callback_list; - if (store) { - CallbackInfo c = {entry, callback, result}; - callback_list.push_back(c); - } else { - for (size_t i = 0; i < callback_list.size(); i++) { - CallbackInfo& c = callback_list[i]; - c.entry->CallbackLater(c.callback, c.result); - } - callback_list.clear(); - } - } - - std::string key_; - std::vector<char> data_[kNumCacheEntryDataIndices]; - int test_mode_; - bool doomed_; - bool sparse_; - bool fail_requests_; - bool busy_; - bool delayed_; - static bool cancel_; - static bool ignore_callbacks_; -}; - -// Statics. -bool MockDiskEntry::cancel_ = false; -bool MockDiskEntry::ignore_callbacks_ = false; - -class MockDiskCache : public disk_cache::Backend { - public: - MockDiskCache() - : open_count_(0), create_count_(0), fail_requests_(false), - soft_failures_(false) { - } - - ~MockDiskCache() { - ReleaseAll(); - } - - virtual int32 GetEntryCount() const { - return static_cast<int32>(entries_.size()); - } - - virtual int OpenEntry(const std::string& key, disk_cache::Entry** entry, - net::OldCompletionCallback* callback) { - DCHECK(callback); - if (fail_requests_) - return net::ERR_CACHE_OPEN_FAILURE; - - EntryMap::iterator it = entries_.find(key); - if (it == entries_.end()) - return net::ERR_CACHE_OPEN_FAILURE; - - if (it->second->is_doomed()) { - it->second->Release(); - entries_.erase(it); - return net::ERR_CACHE_OPEN_FAILURE; - } - - open_count_++; - - it->second->AddRef(); - *entry = it->second; - - if (soft_failures_) - it->second->set_fail_requests(); - - if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) - return net::OK; - - CallbackLater(callback, net::OK); - return net::ERR_IO_PENDING; - } - - virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, - net::OldCompletionCallback* callback) { - DCHECK(callback); - if (fail_requests_) - return net::ERR_CACHE_CREATE_FAILURE; - - EntryMap::iterator it = entries_.find(key); - if (it != entries_.end()) { - DCHECK(it->second->is_doomed()); - it->second->Release(); - entries_.erase(it); - } - - create_count_++; - - MockDiskEntry* new_entry = new MockDiskEntry(key); - - new_entry->AddRef(); - entries_[key] = new_entry; - - new_entry->AddRef(); - *entry = new_entry; - - if (soft_failures_) - new_entry->set_fail_requests(); - - if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) - return net::OK; - - CallbackLater(callback, net::OK); - return net::ERR_IO_PENDING; - } - - virtual int DoomEntry(const std::string& key, - net::OldCompletionCallback* callback) { - DCHECK(callback); - EntryMap::iterator it = entries_.find(key); - if (it != entries_.end()) { - it->second->Release(); - entries_.erase(it); - } - - if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) - return net::OK; - - CallbackLater(callback, net::OK); - return net::ERR_IO_PENDING; - } - - virtual int DoomAllEntries(net::OldCompletionCallback* callback) { - return net::ERR_NOT_IMPLEMENTED; - } - - virtual int DoomEntriesBetween(const base::Time initial_time, - const base::Time end_time, - net::OldCompletionCallback* callback) { - return net::ERR_NOT_IMPLEMENTED; - } - - virtual int DoomEntriesSince(const base::Time initial_time, - net::OldCompletionCallback* callback) { - return net::ERR_NOT_IMPLEMENTED; - } - - virtual int OpenNextEntry(void** iter, disk_cache::Entry** next_entry, - net::OldCompletionCallback* callback) { - return net::ERR_NOT_IMPLEMENTED; - } - - virtual void EndEnumeration(void** iter) {} - - virtual void GetStats( - std::vector<std::pair<std::string, std::string> >* stats) { - } - - virtual void OnExternalCacheHit(const std::string& key) {} - - // returns number of times a cache entry was successfully opened - int open_count() const { return open_count_; } - - // returns number of times a cache entry was successfully created - int create_count() const { return create_count_; } - - // Fail any subsequent CreateEntry and OpenEntry. - void set_fail_requests() { fail_requests_ = true; } - - // Return entries that fail some of their requests. - void set_soft_failures(bool value) { soft_failures_ = value; } - - void ReleaseAll() { - EntryMap::iterator it = entries_.begin(); - for (; it != entries_.end(); ++it) - it->second->Release(); - entries_.clear(); - } - - private: - typedef base::hash_map<std::string, MockDiskEntry*> EntryMap; - - class CallbackRunner : public Task { - public: - CallbackRunner(net::OldCompletionCallback* callback, int result) - : callback_(callback), result_(result) {} - virtual void Run() { - callback_->Run(result_); - } - - private: - net::OldCompletionCallback* callback_; - int result_; - DISALLOW_COPY_AND_ASSIGN(CallbackRunner); - }; - - void CallbackLater(net::OldCompletionCallback* callback, int result) { - MessageLoop::current()->PostTask(FROM_HERE, - new CallbackRunner(callback, result)); - } - - EntryMap entries_; - int open_count_; - int create_count_; - bool fail_requests_; - bool soft_failures_; -}; - -class MockBackendFactory : public net::HttpCache::BackendFactory { - public: - virtual int CreateBackend(net::NetLog* /* net_log */, - disk_cache::Backend** backend, - net::OldCompletionCallback* callback) { - *backend = new MockDiskCache(); - return net::OK; - } -}; - -class MockHttpCache { - public: - MockHttpCache() - : http_cache_(new MockNetworkLayer(), NULL, new MockBackendFactory()) { - } - - explicit MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory) - : http_cache_(new MockNetworkLayer(), NULL, disk_cache_factory) { - } - - net::HttpCache* http_cache() { return &http_cache_; } - - MockNetworkLayer* network_layer() { - return static_cast<MockNetworkLayer*>(http_cache_.network_layer()); - } - MockDiskCache* disk_cache() { - TestOldCompletionCallback cb; - disk_cache::Backend* backend; - int rv = http_cache_.GetBackend(&backend, &cb); - rv = cb.GetResult(rv); - return (rv == net::OK) ? static_cast<MockDiskCache*>(backend) : NULL; - } - - // Helper function for reading response info from the disk cache. - static bool ReadResponseInfo(disk_cache::Entry* disk_entry, - net::HttpResponseInfo* response_info, - bool* response_truncated) { - int size = disk_entry->GetDataSize(0); - - TestOldCompletionCallback cb; - scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); - int rv = disk_entry->ReadData(0, 0, buffer, size, &cb); - rv = cb.GetResult(rv); - EXPECT_EQ(size, rv); - - return net::HttpCache::ParseResponseInfo(buffer->data(), size, - response_info, - response_truncated); - } - - // Helper function for writing response info into the disk cache. - static bool WriteResponseInfo(disk_cache::Entry* disk_entry, - const net::HttpResponseInfo* response_info, - bool skip_transient_headers, - bool response_truncated) { - Pickle pickle; - response_info->Persist( - &pickle, skip_transient_headers, response_truncated); - - TestOldCompletionCallback cb; - scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer( - reinterpret_cast<const char*>(pickle.data()))); - int len = static_cast<int>(pickle.size()); - - int rv = disk_entry->WriteData(0, 0, data, len, &cb, true); - rv = cb.GetResult(rv); - return (rv == len); - } - - // Helper function to synchronously open a backend entry. - bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry) { - TestOldCompletionCallback cb; - int rv = disk_cache()->OpenEntry(key, entry, &cb); - return (cb.GetResult(rv) == net::OK); - } - - // Helper function to synchronously create a backend entry. - bool CreateBackendEntry(const std::string& key, disk_cache::Entry** entry, - net::NetLog* /* net_log */) { - TestOldCompletionCallback cb; - int rv = disk_cache()->CreateEntry(key, entry, &cb); - return (cb.GetResult(rv) == net::OK); - } - - private: - net::HttpCache http_cache_; -}; - -// This version of the disk cache doesn't invoke CreateEntry callbacks. -class MockDiskCacheNoCB : public MockDiskCache { - virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, - net::OldCompletionCallback* callback) { - return net::ERR_IO_PENDING; - } -}; - -class MockBackendNoCbFactory : public net::HttpCache::BackendFactory { - public: - virtual int CreateBackend(net::NetLog* /* net_log */, - disk_cache::Backend** backend, - net::OldCompletionCallback* 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(net::NetLog* /* net_log */, - disk_cache::Backend** backend, - net::OldCompletionCallback* 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::OldCompletionCallback* cb = callback_; - callback_ = NULL; - cb->Run(Result()); // This object can be deleted here. - } - } - - disk_cache::Backend** backend() { return backend_; } - void set_fail(bool fail) { fail_ = fail; } - - net::OldCompletionCallback* callback() { return callback_; } - - private: - int Result() { return fail_ ? net::ERR_FAILED : net::OK; } - - disk_cache::Backend** backend_; - net::OldCompletionCallback* callback_; - bool block_; - bool fail_; -}; - class DeleteCacheOldCompletionCallback : public TestOldCompletionCallback { public: explicit DeleteCacheOldCompletionCallback(MockHttpCache* cache) @@ -1041,7 +380,7 @@ struct Context { //----------------------------------------------------------------------------- -// HttpCache tests +// Tests. TEST(HttpCache, CreateThenDestroy) { MockHttpCache cache; @@ -4341,11 +3680,11 @@ TEST(HttpCache, SetTruncatedFlag) { EXPECT_EQ(net::ERR_IO_PENDING, rv); EXPECT_FALSE(c->callback.have_result()); - g_test_mode = TEST_MODE_SYNC_ALL; + MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL); // Destroy the transaction. c->trans.reset(); - g_test_mode = 0; + MockHttpCache::SetTestMode(0); // Make sure that we don't invoke the callback. We may have an issue if the // UrlRequestJob is killed directly (without cancelling the UrlRequest) so we @@ -5321,41 +4660,3 @@ TEST(HttpCache, TruncatedByContentLength2) { EXPECT_TRUE(truncated); entry->Close(); } - -//----------------------------------------------------------------------------- -// DiskCacheBasedSSLHostInfo tests - -class DeleteSSLHostInfoOldCompletionCallback : public TestOldCompletionCallback { - public: - explicit DeleteSSLHostInfoOldCompletionCallback(net::SSLHostInfo* ssl_host_info) - : ssl_host_info_(ssl_host_info) {} - - virtual void RunWithParams(const Tuple1<int>& params) { - delete ssl_host_info_; - TestOldCompletionCallback::RunWithParams(params); - } - - private: - net::SSLHostInfo* ssl_host_info_; -}; - -// Tests that we can delete a DiskCacheBasedSSLHostInfo object in a -// completion callback for DiskCacheBasedSSLHostInfo::WaitForDataReady. -TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) { - net::CertVerifier cert_verifier; - // Use the blocking mock backend factory to force asynchronous completion - // of ssl_host_info->WaitForDataReady(), so that the callback will run. - MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); - MockHttpCache cache(factory); - net::SSLConfig ssl_config; - net::SSLHostInfo* ssl_host_info = - new net::DiskCacheBasedSSLHostInfo("https://www.verisign.com", ssl_config, - &cert_verifier, cache.http_cache()); - ssl_host_info->Start(); - DeleteSSLHostInfoOldCompletionCallback callback(ssl_host_info); - int rv = ssl_host_info->WaitForDataReady(&callback); - EXPECT_EQ(net::ERR_IO_PENDING, rv); - // Now complete the backend creation and let the callback run. - factory->FinishCreation(); - EXPECT_EQ(net::OK, callback.GetResult(rv)); -} diff --git a/net/http/mock_http_cache.cc b/net/http/mock_http_cache.cc new file mode 100644 index 0000000..181e104 --- /dev/null +++ b/net/http/mock_http_cache.cc @@ -0,0 +1,613 @@ +// Copyright (c) 2011 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. + +#include "net/http/mock_http_cache.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "net/base/net_errors.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +int GetTestModeForEntry(const std::string& key) { + // 'key' is prefixed with an identifier if it corresponds to a cached POST. + // Skip past that to locate the actual URL. + // + // TODO(darin): It breaks the abstraction a bit that we assume 'key' is an + // URL corresponding to a registered MockTransaction. It would be good to + // have another way to access the test_mode. + GURL url; + if (isdigit(key[0])) { + size_t slash = key.find('/'); + DCHECK(slash != std::string::npos); + url = GURL(key.substr(slash + 1)); + } else { + url = GURL(key); + } + const MockTransaction* t = FindMockTransaction(url); + DCHECK(t); + return t->test_mode; +} + +// We can override the test mode for a given operation by setting this global +// variable. +int g_test_mode = 0; + +} // namespace + +//----------------------------------------------------------------------------- + +struct MockDiskEntry::CallbackInfo { + scoped_refptr<MockDiskEntry> entry; + net::OldCompletionCallback* callback; + int result; +}; + +MockDiskEntry::MockDiskEntry() + : test_mode_(0), doomed_(false), sparse_(false), + fail_requests_(false), busy_(false), delayed_(false) { +} + +MockDiskEntry::MockDiskEntry(const std::string& key) + : key_(key), doomed_(false), sparse_(false), + fail_requests_(false), busy_(false), delayed_(false) { + test_mode_ = GetTestModeForEntry(key); +} + +void MockDiskEntry::Doom() { + doomed_ = true; +} + +void MockDiskEntry::Close() { + Release(); +} + +std::string MockDiskEntry::GetKey() const { + if (fail_requests_) + return std::string(); + return key_; +} + +base::Time MockDiskEntry::GetLastUsed() const { + return base::Time::FromInternalValue(0); +} + +base::Time MockDiskEntry::GetLastModified() const { + return base::Time::FromInternalValue(0); +} + +int32 MockDiskEntry::GetDataSize(int index) const { + DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); + return static_cast<int32>(data_[index].size()); +} + +int MockDiskEntry::ReadData(int index, int offset, net::IOBuffer* buf, + int buf_len, net::OldCompletionCallback* callback) { + DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); + DCHECK(callback); + + if (fail_requests_) + return net::ERR_CACHE_READ_FAILURE; + + if (offset < 0 || offset > static_cast<int>(data_[index].size())) + return net::ERR_FAILED; + if (static_cast<size_t>(offset) == data_[index].size()) + return 0; + + int num = std::min(buf_len, static_cast<int>(data_[index].size()) - offset); + memcpy(buf->data(), &data_[index][offset], num); + + if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) + return num; + + CallbackLater(callback, num); + return net::ERR_IO_PENDING; +} + +int MockDiskEntry::WriteData(int index, int offset, net::IOBuffer* buf, + int buf_len, net::OldCompletionCallback* callback, + bool truncate) { + DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); + DCHECK(callback); + DCHECK(truncate); + + if (fail_requests_) { + CallbackLater(callback, net::ERR_CACHE_READ_FAILURE); + return net::ERR_IO_PENDING; + } + + if (offset < 0 || offset > static_cast<int>(data_[index].size())) + return net::ERR_FAILED; + + data_[index].resize(offset + buf_len); + if (buf_len) + memcpy(&data_[index][offset], buf->data(), buf_len); + + if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) + return buf_len; + + CallbackLater(callback, buf_len); + return net::ERR_IO_PENDING; +} + +int MockDiskEntry::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::OldCompletionCallback* callback) { + DCHECK(callback); + if (!sparse_ || busy_) + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + if (offset < 0) + return net::ERR_FAILED; + + if (fail_requests_) + return net::ERR_CACHE_READ_FAILURE; + + DCHECK(offset < kint32max); + int real_offset = static_cast<int>(offset); + if (!buf_len) + return 0; + + int num = std::min(static_cast<int>(data_[1].size()) - real_offset, + buf_len); + memcpy(buf->data(), &data_[1][real_offset], num); + + if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) + return num; + + CallbackLater(callback, num); + busy_ = true; + delayed_ = false; + return net::ERR_IO_PENDING; +} + +int MockDiskEntry::WriteSparseData(int64 offset, net::IOBuffer* buf, + int buf_len, + net::OldCompletionCallback* callback) { + DCHECK(callback); + if (busy_) + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + if (!sparse_) { + if (data_[1].size()) + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + sparse_ = true; + } + if (offset < 0) + return net::ERR_FAILED; + if (!buf_len) + return 0; + + if (fail_requests_) + return net::ERR_CACHE_READ_FAILURE; + + DCHECK(offset < kint32max); + int real_offset = static_cast<int>(offset); + + if (static_cast<int>(data_[1].size()) < real_offset + buf_len) + data_[1].resize(real_offset + buf_len); + + memcpy(&data_[1][real_offset], buf->data(), buf_len); + if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) + return buf_len; + + CallbackLater(callback, buf_len); + return net::ERR_IO_PENDING; +} + +int MockDiskEntry::GetAvailableRange(int64 offset, int len, int64* start, + net::OldCompletionCallback* callback) { + DCHECK(callback); + if (!sparse_ || busy_) + return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + if (offset < 0) + return net::ERR_FAILED; + + if (fail_requests_) + return net::ERR_CACHE_READ_FAILURE; + + *start = offset; + DCHECK(offset < kint32max); + int real_offset = static_cast<int>(offset); + if (static_cast<int>(data_[1].size()) < real_offset) + return 0; + + int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len); + int count = 0; + for (; num > 0; num--, real_offset++) { + if (!count) { + if (data_[1][real_offset]) { + count++; + *start = real_offset; + } + } else { + if (!data_[1][real_offset]) + break; + count++; + } + } + if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) + return count; + + CallbackLater(callback, count); + return net::ERR_IO_PENDING; +} + +bool MockDiskEntry::CouldBeSparse() const { + return sparse_; +} + +void MockDiskEntry::CancelSparseIO() { + cancel_ = true; +} + +int MockDiskEntry::ReadyForSparseIO(net::OldCompletionCallback* callback) { + if (!cancel_) + return net::OK; + + cancel_ = false; + DCHECK(callback); + if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) + return net::OK; + + // The pending operation is already in the message loop (and hopefuly + // already in the second pass). Just notify the caller that it finished. + CallbackLater(callback, 0); + return net::ERR_IO_PENDING; +} + +// If |value| is true, don't deliver any completion callbacks until called +// again with |value| set to false. Caution: remember to enable callbacks +// again or all subsequent tests will fail. +// Static. +void MockDiskEntry::IgnoreCallbacks(bool value) { + if (ignore_callbacks_ == value) + return; + ignore_callbacks_ = value; + if (!value) + StoreAndDeliverCallbacks(false, NULL, NULL, 0); +} + +MockDiskEntry::~MockDiskEntry() { +} + +// Unlike the callbacks for MockHttpTransaction, we want this one to run even +// if the consumer called Close on the MockDiskEntry. We achieve that by +// leveraging the fact that this class is reference counted. +void MockDiskEntry::CallbackLater(net::OldCompletionCallback* callback, + int result) { + if (ignore_callbacks_) + return StoreAndDeliverCallbacks(true, this, callback, result); + MessageLoop::current()->PostTask(FROM_HERE, base::Bind( + &MockDiskEntry::RunCallback, this, callback, result)); +} + +void MockDiskEntry::RunCallback(net::OldCompletionCallback* callback, int result) { + if (busy_) { + // This is kind of hacky, but controlling the behavior of just this entry + // from a test is sort of complicated. What we really want to do is + // delay the delivery of a sparse IO operation a little more so that the + // request start operation (async) will finish without seeing the end of + // this operation (already posted to the message loop)... and without + // just delaying for n mS (which may cause trouble with slow bots). So + // we re-post this operation (all async sparse IO operations will take two + // trips trhough the message loop instead of one). + if (!delayed_) { + delayed_ = true; + return CallbackLater(callback, result); + } + } + busy_ = false; + callback->Run(result); +} + +// When |store| is true, stores the callback to be delivered later; otherwise +// delivers any callback previously stored. +// Static. +void MockDiskEntry::StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry, + net::OldCompletionCallback* callback, + int result) { + static std::vector<CallbackInfo> callback_list; + if (store) { + CallbackInfo c = {entry, callback, result}; + callback_list.push_back(c); + } else { + for (size_t i = 0; i < callback_list.size(); i++) { + CallbackInfo& c = callback_list[i]; + c.entry->CallbackLater(c.callback, c.result); + } + callback_list.clear(); + } +} + +// Statics. +bool MockDiskEntry::cancel_ = false; +bool MockDiskEntry::ignore_callbacks_ = false; + +//----------------------------------------------------------------------------- + +class MockDiskCache::CallbackRunner : public Task { + public: + CallbackRunner(net::OldCompletionCallback* callback, int result) + : callback_(callback), result_(result) {} + virtual void Run() { + callback_->Run(result_); + } + + private: + net::OldCompletionCallback* callback_; + int result_; + DISALLOW_COPY_AND_ASSIGN(CallbackRunner); +}; + +MockDiskCache::MockDiskCache() + : open_count_(0), create_count_(0), fail_requests_(false), + soft_failures_(false) { +} + +MockDiskCache::~MockDiskCache() { + ReleaseAll(); +} + +int32 MockDiskCache::GetEntryCount() const { + return static_cast<int32>(entries_.size()); +} + +int MockDiskCache::OpenEntry(const std::string& key, disk_cache::Entry** entry, + net::OldCompletionCallback* callback) { + DCHECK(callback); + if (fail_requests_) + return net::ERR_CACHE_OPEN_FAILURE; + + EntryMap::iterator it = entries_.find(key); + if (it == entries_.end()) + return net::ERR_CACHE_OPEN_FAILURE; + + if (it->second->is_doomed()) { + it->second->Release(); + entries_.erase(it); + return net::ERR_CACHE_OPEN_FAILURE; + } + + open_count_++; + + it->second->AddRef(); + *entry = it->second; + + if (soft_failures_) + it->second->set_fail_requests(); + + if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) + return net::OK; + + CallbackLater(callback, net::OK); + return net::ERR_IO_PENDING; +} + +int MockDiskCache::CreateEntry(const std::string& key, + disk_cache::Entry** entry, + net::OldCompletionCallback* callback) { + DCHECK(callback); + if (fail_requests_) + return net::ERR_CACHE_CREATE_FAILURE; + + EntryMap::iterator it = entries_.find(key); + if (it != entries_.end()) { + DCHECK(it->second->is_doomed()); + it->second->Release(); + entries_.erase(it); + } + + create_count_++; + + MockDiskEntry* new_entry = new MockDiskEntry(key); + + new_entry->AddRef(); + entries_[key] = new_entry; + + new_entry->AddRef(); + *entry = new_entry; + + if (soft_failures_) + new_entry->set_fail_requests(); + + if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) + return net::OK; + + CallbackLater(callback, net::OK); + return net::ERR_IO_PENDING; +} + +int MockDiskCache::DoomEntry(const std::string& key, + net::OldCompletionCallback* callback) { + DCHECK(callback); + EntryMap::iterator it = entries_.find(key); + if (it != entries_.end()) { + it->second->Release(); + entries_.erase(it); + } + + if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) + return net::OK; + + CallbackLater(callback, net::OK); + return net::ERR_IO_PENDING; +} + +int MockDiskCache::DoomAllEntries(net::OldCompletionCallback* callback) { + return net::ERR_NOT_IMPLEMENTED; +} + +int MockDiskCache::DoomEntriesBetween(const base::Time initial_time, + const base::Time end_time, + net::OldCompletionCallback* callback) { + return net::ERR_NOT_IMPLEMENTED; +} + +int MockDiskCache::DoomEntriesSince(const base::Time initial_time, + net::OldCompletionCallback* callback) { + return net::ERR_NOT_IMPLEMENTED; +} + +int MockDiskCache::OpenNextEntry(void** iter, disk_cache::Entry** next_entry, + net::OldCompletionCallback* callback) { + return net::ERR_NOT_IMPLEMENTED; +} + +void MockDiskCache::EndEnumeration(void** iter) { +} + +void MockDiskCache::GetStats( + std::vector<std::pair<std::string, std::string> >* stats) { +} + +void MockDiskCache::OnExternalCacheHit(const std::string& key) { +} + +void MockDiskCache::ReleaseAll() { + EntryMap::iterator it = entries_.begin(); + for (; it != entries_.end(); ++it) + it->second->Release(); + entries_.clear(); +} + +void MockDiskCache::CallbackLater(net::OldCompletionCallback* callback, + int result) { + MessageLoop::current()->PostTask(FROM_HERE, + new CallbackRunner(callback, result)); +} + +//----------------------------------------------------------------------------- + +int MockBackendFactory::CreateBackend(net::NetLog* net_log, + disk_cache::Backend** backend, + net::OldCompletionCallback* callback) { + *backend = new MockDiskCache(); + return net::OK; +} + +//----------------------------------------------------------------------------- + +MockHttpCache::MockHttpCache() + : http_cache_(new MockNetworkLayer(), NULL, new MockBackendFactory()) { +} + +MockHttpCache::MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory) + : http_cache_(new MockNetworkLayer(), NULL, disk_cache_factory) { +} + +MockDiskCache* MockHttpCache::disk_cache() { + TestOldCompletionCallback cb; + disk_cache::Backend* backend; + int rv = http_cache_.GetBackend(&backend, &cb); + rv = cb.GetResult(rv); + return (rv == net::OK) ? static_cast<MockDiskCache*>(backend) : NULL; +} + +bool MockHttpCache::ReadResponseInfo(disk_cache::Entry* disk_entry, + net::HttpResponseInfo* response_info, + bool* response_truncated) { + int size = disk_entry->GetDataSize(0); + + TestOldCompletionCallback cb; + scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); + int rv = disk_entry->ReadData(0, 0, buffer, size, &cb); + rv = cb.GetResult(rv); + EXPECT_EQ(size, rv); + + return net::HttpCache::ParseResponseInfo(buffer->data(), size, + response_info, + response_truncated); +} + +bool MockHttpCache::WriteResponseInfo( + disk_cache::Entry* disk_entry, const net::HttpResponseInfo* response_info, + bool skip_transient_headers, bool response_truncated) { + Pickle pickle; + response_info->Persist( + &pickle, skip_transient_headers, response_truncated); + + TestOldCompletionCallback cb; + scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer( + reinterpret_cast<const char*>(pickle.data()))); + int len = static_cast<int>(pickle.size()); + + int rv = disk_entry->WriteData(0, 0, data, len, &cb, true); + rv = cb.GetResult(rv); + return (rv == len); +} + +bool MockHttpCache::OpenBackendEntry(const std::string& key, + disk_cache::Entry** entry) { + TestOldCompletionCallback cb; + int rv = disk_cache()->OpenEntry(key, entry, &cb); + return (cb.GetResult(rv) == net::OK); +} + +bool MockHttpCache::CreateBackendEntry(const std::string& key, + disk_cache::Entry** entry, + net::NetLog* net_log) { + TestOldCompletionCallback cb; + int rv = disk_cache()->CreateEntry(key, entry, &cb); + return (cb.GetResult(rv) == net::OK); +} + +// Static. +int MockHttpCache::GetTestMode(int test_mode) { + if (!g_test_mode) + return test_mode; + + return g_test_mode; +} + +// Static. +void MockHttpCache::SetTestMode(int test_mode) { + g_test_mode = test_mode; +} + +//----------------------------------------------------------------------------- + +int MockDiskCacheNoCB::CreateEntry(const std::string& key, + disk_cache::Entry** entry, + net::OldCompletionCallback* callback) { + return net::ERR_IO_PENDING; +} + +//----------------------------------------------------------------------------- + +int MockBackendNoCbFactory::CreateBackend(net::NetLog* net_log, + disk_cache::Backend** backend, + net::OldCompletionCallback* callback) { + *backend = new MockDiskCacheNoCB(); + return net::OK; +} + +//----------------------------------------------------------------------------- + +MockBlockingBackendFactory::MockBlockingBackendFactory() + : backend_(NULL), callback_(NULL), block_(true), fail_(false) { +} + +int MockBlockingBackendFactory::CreateBackend( + net::NetLog* net_log, disk_cache::Backend** backend, + net::OldCompletionCallback* callback) { + if (!block_) { + if (!fail_) + *backend = new MockDiskCache(); + return Result(); + } + + backend_ = backend; + callback_ = callback; + return net::ERR_IO_PENDING; +} + +void MockBlockingBackendFactory::FinishCreation() { + block_ = false; + if (callback_) { + if (!fail_) + *backend_ = new MockDiskCache(); + net::OldCompletionCallback* cb = callback_; + callback_ = NULL; + cb->Run(Result()); // This object can be deleted here. + } +} diff --git a/net/http/mock_http_cache.h b/net/http/mock_http_cache.h new file mode 100644 index 0000000..a4bd83f --- /dev/null +++ b/net/http/mock_http_cache.h @@ -0,0 +1,233 @@ +// Copyright (c) 2011 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. + +// This is a mock of the http cache and related testing classes. To be fair, it +// is not really a mock http cache given that it uses the real implementation of +// the http cache, but it has fake implementations of all required components, +// so it is useful for unit tests at the http layer. + +#ifndef NET_HTTP_MOCK_HTTP_CACHE_H_ +#define NET_HTTP_MOCK_HTTP_CACHE_H_ +#pragma once + +#include "base/hash_tables.h" +#include "net/disk_cache/disk_cache.h" +#include "net/http/http_cache.h" +#include "net/http/http_transaction_unittest.h" + +//----------------------------------------------------------------------------- +// Mock disk cache (a very basic memory cache implementation). + +class MockDiskEntry : public disk_cache::Entry, + public base::RefCounted<MockDiskEntry> { + public: + MockDiskEntry(); + explicit MockDiskEntry(const std::string& key); + + bool is_doomed() const { return doomed_; } + + virtual void Doom() OVERRIDE; + virtual void Close() OVERRIDE; + virtual std::string GetKey() const OVERRIDE; + virtual base::Time GetLastUsed() const OVERRIDE; + virtual base::Time GetLastModified() const OVERRIDE; + virtual int32 GetDataSize(int index) const OVERRIDE; + virtual int ReadData(int index, int offset, net::IOBuffer* buf, int buf_len, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, + net::OldCompletionCallback* callback, + bool truncate) OVERRIDE; + virtual int ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int GetAvailableRange(int64 offset, int len, int64* start, + net::OldCompletionCallback* callback) OVERRIDE; + virtual bool CouldBeSparse() const OVERRIDE; + virtual void CancelSparseIO() OVERRIDE; + virtual int ReadyForSparseIO( + net::OldCompletionCallback* completion_callback) OVERRIDE; + + // Fail most subsequent requests. + void set_fail_requests() { fail_requests_ = true; } + + // If |value| is true, don't deliver any completion callbacks until called + // again with |value| set to false. Caution: remember to enable callbacks + // again or all subsequent tests will fail. + static void IgnoreCallbacks(bool value); + + private: + friend class base::RefCounted<MockDiskEntry>; + struct CallbackInfo; + + virtual ~MockDiskEntry(); + + // Unlike the callbacks for MockHttpTransaction, we want this one to run even + // if the consumer called Close on the MockDiskEntry. We achieve that by + // leveraging the fact that this class is reference counted. + void CallbackLater(net::OldCompletionCallback* callback, int result); + + void RunCallback(net::OldCompletionCallback* callback, int result); + + // When |store| is true, stores the callback to be delivered later; otherwise + // delivers any callback previously stored. + static void StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry, + net::OldCompletionCallback* callback, + int result); + + static const int kNumCacheEntryDataIndices = 3; + + std::string key_; + std::vector<char> data_[kNumCacheEntryDataIndices]; + int test_mode_; + bool doomed_; + bool sparse_; + bool fail_requests_; + bool busy_; + bool delayed_; + static bool cancel_; + static bool ignore_callbacks_; +}; + +class MockDiskCache : public disk_cache::Backend { + public: + MockDiskCache(); + virtual ~MockDiskCache(); + + virtual int32 GetEntryCount() const OVERRIDE; + virtual int OpenEntry(const std::string& key, disk_cache::Entry** entry, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int DoomEntry(const std::string& key, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int DoomAllEntries(net::OldCompletionCallback* callback) OVERRIDE; + virtual int DoomEntriesBetween(const base::Time initial_time, + const base::Time end_time, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int DoomEntriesSince(const base::Time initial_time, + net::OldCompletionCallback* callback) OVERRIDE; + virtual int OpenNextEntry(void** iter, disk_cache::Entry** next_entry, + net::OldCompletionCallback* callback) OVERRIDE; + virtual void EndEnumeration(void** iter) OVERRIDE; + virtual void GetStats( + std::vector<std::pair<std::string, std::string> >* stats) OVERRIDE; + virtual void OnExternalCacheHit(const std::string& key) OVERRIDE; + + // returns number of times a cache entry was successfully opened + int open_count() const { return open_count_; } + + // returns number of times a cache entry was successfully created + int create_count() const { return create_count_; } + + // Fail any subsequent CreateEntry and OpenEntry. + void set_fail_requests() { fail_requests_ = true; } + + // Return entries that fail some of their requests. + void set_soft_failures(bool value) { soft_failures_ = value; } + + void ReleaseAll(); + + private: + typedef base::hash_map<std::string, MockDiskEntry*> EntryMap; + class CallbackRunner; + + void CallbackLater(net::OldCompletionCallback* callback, int result); + + EntryMap entries_; + int open_count_; + int create_count_; + bool fail_requests_; + bool soft_failures_; +}; + +class MockBackendFactory : public net::HttpCache::BackendFactory { + public: + virtual int CreateBackend(net::NetLog* net_log, + disk_cache::Backend** backend, + net::OldCompletionCallback* callback) OVERRIDE; +}; + +class MockHttpCache { + public: + MockHttpCache(); + explicit MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory); + + net::HttpCache* http_cache() { return &http_cache_; } + + MockNetworkLayer* network_layer() { + return static_cast<MockNetworkLayer*>(http_cache_.network_layer()); + } + MockDiskCache* disk_cache(); + + // Helper function for reading response info from the disk cache. + static bool ReadResponseInfo(disk_cache::Entry* disk_entry, + net::HttpResponseInfo* response_info, + bool* response_truncated); + + // Helper function for writing response info into the disk cache. + static bool WriteResponseInfo(disk_cache::Entry* disk_entry, + const net::HttpResponseInfo* response_info, + bool skip_transient_headers, + bool response_truncated); + + // Helper function to synchronously open a backend entry. + bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry); + + // Helper function to synchronously create a backend entry. + bool CreateBackendEntry(const std::string& key, disk_cache::Entry** entry, + net::NetLog* net_log); + + // Returns the test mode after considering the global override. + static int GetTestMode(int test_mode); + + // Overrides the test mode for a given operation. Remember to reset it after + // the test! (by setting test_mode to zero). + static void SetTestMode(int test_mode); + + private: + net::HttpCache http_cache_; +}; + +// This version of the disk cache doesn't invoke CreateEntry callbacks. +class MockDiskCacheNoCB : public MockDiskCache { + virtual int CreateEntry(const std::string& key, disk_cache::Entry** entry, + net::OldCompletionCallback* callback) OVERRIDE; +}; + +class MockBackendNoCbFactory : public net::HttpCache::BackendFactory { + public: + virtual int CreateBackend(net::NetLog* net_log, + disk_cache::Backend** backend, + net::OldCompletionCallback* callback) OVERRIDE; +}; + +// This backend factory allows us to control the backend instantiation. +class MockBlockingBackendFactory : public net::HttpCache::BackendFactory { + public: + MockBlockingBackendFactory(); + + virtual int CreateBackend(net::NetLog* net_log, + disk_cache::Backend** backend, + net::OldCompletionCallback* callback) OVERRIDE; + + // Completes the backend creation. Any blocked call will be notified via the + // provided callback. + void FinishCreation(); + + disk_cache::Backend** backend() { return backend_; } + void set_fail(bool fail) { fail_ = fail; } + + net::OldCompletionCallback* callback() { return callback_; } + + private: + int Result() { return fail_ ? net::ERR_FAILED : net::OK; } + + disk_cache::Backend** backend_; + net::OldCompletionCallback* callback_; + bool block_; + bool fail_; +}; + +#endif // NET_HTTP_MOCK_HTTP_CACHE_H_ diff --git a/net/net.gyp b/net/net.gyp index 432b558..e84ea03d 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -1068,6 +1068,7 @@ 'ftp/ftp_network_transaction_unittest.cc', 'ftp/ftp_util_unittest.cc', 'http/des_unittest.cc', + 'http/disk_cache_based_ssl_host_info_unittest.cc', 'http/http_auth_cache_unittest.cc', 'http/http_auth_controller_unittest.cc', 'http/http_auth_filter_unittest.cc', @@ -1104,6 +1105,8 @@ 'http/mock_allow_url_security_manager.h', 'http/mock_gssapi_library_posix.cc', 'http/mock_gssapi_library_posix.h', + 'http/mock_http_cache.cc', + 'http/mock_http_cache.h', 'http/mock_sspi_library_win.h', 'http/mock_sspi_library_win.cc', 'http/url_security_manager_unittest.cc', |