diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-15 22:04:32 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-15 22:04:32 +0000 |
commit | b59ff376c5d5b950774fcbe65727611d51832b75 (patch) | |
tree | a37598ddd4e9ec0530d5820bcce1f47bafa89289 /net/base/mock_host_resolver.cc | |
parent | 89d70652ad0bb9e7f419c17516fad279d8a4db32 (diff) | |
download | chromium_src-b59ff376c5d5b950774fcbe65727611d51832b75.zip chromium_src-b59ff376c5d5b950774fcbe65727611d51832b75.tar.gz chromium_src-b59ff376c5d5b950774fcbe65727611d51832b75.tar.bz2 |
Refactorings surrounding HostResolver:
(1) Extract HostResolver to an interface.
The existing concrete implementation is now named HostResolverImpl. This makes it possible to create mocks with more complex behavior (i.e. choose via rules if response will be sync vs async).
(2) Transform HostMapper into HostResolverProc.
Conceptually HostResolverProc maps a hostname to a socket address, whereas HostMapper mapped a hostname to another hostname (so you were still at the mercy of the system's host resolver). With HostResolverProc you can specify the exact AddressList, making it possible to run tests requiring IPv6 socketaddrs on systems (like WinXP) that don't actually support it.
(3) Add a MockHostResolver implementation of HostResolver.
This replaces the [ScopedHostMapper + RuleBasedHostMapper + HostResolver] combo. It is less clunky and a bit more expressive.
BUG=http://crbug.com/16452
R=willchan
TEST=existing
Review URL: http://codereview.chromium.org/149511
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20795 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/mock_host_resolver.cc')
-rw-r--r-- | net/base/mock_host_resolver.cc | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc new file mode 100644 index 0000000..58ad552 --- /dev/null +++ b/net/base/mock_host_resolver.cc @@ -0,0 +1,154 @@ +// Copyright (c) 2009 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/mock_host_resolver.h" + +#include "base/string_util.h" +#include "base/platform_thread.h" +#include "base/ref_counted.h" +#include "net/base/net_errors.h" + +namespace net { + +MockHostResolver::MockHostResolver() { + Reset(NULL, 0, 0); +} + +int MockHostResolver::Resolve(const RequestInfo& info, + AddressList* addresses, + CompletionCallback* callback, + RequestHandle* out_req) { + return impl_->Resolve(info, addresses, callback, out_req); +} + +void MockHostResolver::CancelRequest(RequestHandle req) { + impl_->CancelRequest(req); +} + +void MockHostResolver::AddObserver(Observer* observer) { + impl_->AddObserver(observer); +} + +void MockHostResolver::RemoveObserver(Observer* observer) { + impl_->RemoveObserver(observer); +} + +void MockHostResolver::Shutdown() { + impl_->Shutdown(); +} + +void MockHostResolver::Reset(HostResolverProc* interceptor, + int max_cache_entries, + int max_cache_age_ms) { + // At the root of the chain, map everything to localhost. + scoped_refptr<RuleBasedHostResolverProc> catchall = + new RuleBasedHostResolverProc(NULL); + catchall->AddRule("*", "127.0.0.1"); + + // Next add a rules-based layer the use controls. + rules_ = new RuleBasedHostResolverProc(catchall); + + HostResolverProc* proc = rules_; + + // Lastly add the provided interceptor to the front of the chain. + if (interceptor) { + interceptor->set_previous_proc(proc); + proc = interceptor; + } + + impl_ = new HostResolverImpl(proc, max_cache_entries, max_cache_age_ms); +} + +//----------------------------------------------------------------------------- + +struct RuleBasedHostResolverProc::Rule { + std::string host_pattern; + std::string replacement; + int latency_ms; // In milliseconds. + bool direct; // if true, don't mangle hostname and ignore replacement + Rule(const std::string& host_pattern, const std::string& replacement) + : host_pattern(host_pattern), + replacement(replacement), + latency_ms(0), + direct(false) {} + Rule(const std::string& host_pattern, const std::string& replacement, + const int latency_ms) + : host_pattern(host_pattern), + replacement(replacement), + latency_ms(latency_ms), + direct(false) {} + Rule(const std::string& host_pattern, const std::string& replacement, + const bool direct) + : host_pattern(host_pattern), + replacement(replacement), + latency_ms(0), + direct(direct) {} +}; + +RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous) + : HostResolverProc(previous) { +} + +RuleBasedHostResolverProc::~RuleBasedHostResolverProc() { +} + +void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern, + const std::string& replacement) { + rules_.push_back(Rule(host_pattern, replacement)); +} + +void RuleBasedHostResolverProc::AddRuleWithLatency( + const std::string& host_pattern, + const std::string& replacement, int latency_ms) { + rules_.push_back(Rule(host_pattern, replacement, latency_ms)); +} + +void RuleBasedHostResolverProc::AllowDirectLookup(const std::string& host) { + rules_.push_back(Rule(host, "", true)); +} + +void RuleBasedHostResolverProc::AddSimulatedFailure(const std::string& host) { + AddRule(host, ""); +} + +int RuleBasedHostResolverProc::Resolve(const std::string& host, + AddressList* addrlist) { + RuleList::iterator r; + for (r = rules_.begin(); r != rules_.end(); ++r) { + if (MatchPattern(host, r->host_pattern)) { + if (r->latency_ms != 0) { + PlatformThread::Sleep(r->latency_ms); + // Hmm, this seems unecessary. + r->latency_ms = 1; + } + const std::string& effective_host = r->direct ? host : r->replacement; + if (effective_host.empty()) + return ERR_NAME_NOT_RESOLVED; + return SystemHostResolverProc(effective_host, addrlist); + } + } + return ResolveUsingPrevious(host, addrlist); +} + +//----------------------------------------------------------------------------- + +ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc( + HostResolverProc* proc) : current_proc_(proc) { + previous_proc_ = HostResolverProc::SetDefault(current_proc_); + current_proc_->set_previous_proc(previous_proc_); +} + +ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() { + HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_); + // The lifetimes of multiple instances must be nested. + CHECK(old_proc == current_proc_); +} + +void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) { + current_proc_ = proc; + previous_proc_ = HostResolverProc::SetDefault(current_proc_); + current_proc_->set_previous_proc(previous_proc_); +} + +} // namespace net |