diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-28 06:29:51 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-28 06:29:51 +0000 |
commit | 74bb68315422a57f06d953065d2b966f234aa0fb (patch) | |
tree | 8daf6eee1e66c3babf24bbcdfa97ad8a7c1ddd0b /net/proxy | |
parent | ff4c6407fb33ae1262d834abe534f3856a038038 (diff) | |
download | chromium_src-74bb68315422a57f06d953065d2b966f234aa0fb.zip chromium_src-74bb68315422a57f06d953065d2b966f234aa0fb.tar.gz chromium_src-74bb68315422a57f06d953065d2b966f234aa0fb.tar.bz2 |
Clean-up proxy_service_unittest.cc, to remove dependency on SingleThreadedProxyResolver.
This was a TODO generated in <http://codereview.chromium.org/149525>
This simplifies the test code since everything is running on one thread.
BUG=http://crbug.com/11746, http://crbug.com/11079
Review URL: http://codereview.chromium.org/160155
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21829 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/proxy')
-rw-r--r-- | net/proxy/proxy_service_unittest.cc | 1351 |
1 files changed, 607 insertions, 744 deletions
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index 1e2e3a5..fb6dda7 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -2,14 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/compiler_specific.h" +#include <vector> + +#include "base/logging.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" #include "net/proxy/proxy_config_service.h" #include "net/proxy/proxy_resolver.h" #include "net/proxy/proxy_script_fetcher.h" #include "net/proxy/proxy_service.h" -#include "net/proxy/single_threaded_proxy_resolver.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -30,469 +32,160 @@ class MockProxyConfigService: public net::ProxyConfigService { net::ProxyConfig config; }; -class SyncMockProxyResolver : public net::ProxyResolver { +// Asynchronous mock proxy resolver. All requests complete asynchronously, +// user must call Request::CompleteNow() on a pending request to signal it. +class MockAsyncProxyResolverBase : public net::ProxyResolver { public: - SyncMockProxyResolver() : net::ProxyResolver(false /*expects_pac_bytes*/), - fail_get_proxy_for_url(false) { - } - - // ProxyResolver implementation: - virtual int GetProxyForURL(const GURL& query_url, - net::ProxyInfo* results, - net::CompletionCallback* callback, - RequestHandle* request) { - if (fail_get_proxy_for_url) - return net::ERR_FAILED; - if (GURL(query_url).host() == info_predicate_query_host) { - results->Use(info); - } else { - results->UseDirect(); + class Request : public base::RefCounted<Request> { + public: + Request(MockAsyncProxyResolverBase* resolver, + const GURL& url, + net::ProxyInfo* results, + net::CompletionCallback* callback) + : resolver_(resolver), + url_(url), + results_(results), + callback_(callback), + origin_loop_(MessageLoop::current()) { } - return net::OK; - } - virtual void CancelRequest(RequestHandle request) { - NOTREACHED(); - } - - virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {} - - - net::ProxyInfo info; - - // info is only returned if query_url in GetProxyForURL matches this: - std::string info_predicate_query_host; + const GURL& url() const { return url_; } + net::ProxyInfo* results() const { return results_; } + net::CompletionCallback* callback() const { return callback_; } - // If true, then GetProxyForURL will fail, which simulates failure to - // download or execute the PAC file. - bool fail_get_proxy_for_url; -}; + void CompleteNow(int rv) { + net::CompletionCallback* callback = callback_; -class MockProxyResolver : public net::SingleThreadedProxyResolver { - public: - MockProxyResolver() - : net::SingleThreadedProxyResolver(new SyncMockProxyResolver) { - x = reinterpret_cast<SyncMockProxyResolver*>(resolver()); - } - - // TODO(eroman): cleanup. - SyncMockProxyResolver* x; -}; - -// ResultFuture is a handle to get at the result from -// ProxyService::ResolveProxyForURL() that ran on another thread. -class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> { - public: - // |service| is the ProxyService to issue requests on, and |io_message_loop| - // is the message loop where ProxyService lives. - ResultFuture(MessageLoop* io_message_loop, - net::ProxyService* service) - : io_message_loop_(io_message_loop), - service_(service), - request_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST( - callback_(this, &ResultFuture::OnCompletion)), - completion_(true, false), - cancelled_(false, false), - started_(false, false), - did_complete_(false) { - } - - // Block until the request has completed, then return the result. - int GetResultCode() { - DCHECK(MessageLoop::current() != io_message_loop_); - WaitUntilCompleted(); - return result_code_; - } - - // Block until the request has completed, then return the result. - const net::ProxyInfo& GetProxyInfo() { - DCHECK(MessageLoop::current() != io_message_loop_); - WaitUntilCompleted(); - return proxy_info_; - } - - // Cancel this request (wait until the cancel has been issued before - // returning). - void Cancel() { - DCHECK(MessageLoop::current() != io_message_loop_); - io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &ResultFuture::DoCancel)); - cancelled_.Wait(); - } - - // Return true if the request has already completed. - bool IsCompleted() { - DCHECK(MessageLoop::current() != io_message_loop_); - return did_complete_; - } - - // Wait until the ProxyService completes this request. - void WaitUntilCompleted() { - DCHECK(MessageLoop::current() != io_message_loop_); - completion_.Wait(); - DCHECK(did_complete_); - } + // May delete |this|. + resolver_->RemovePendingRequest(this); - private: - friend class ProxyServiceWithFutures; - - typedef int (net::ProxyService::*RequestMethod)(const GURL&, net::ProxyInfo*, - net::CompletionCallback*, net::ProxyService::PacRequest**); - - void StartResolve(const GURL& url) { - StartRequest(url, &net::ProxyService::ResolveProxy); - } - - // |proxy_info| is the *previous* result (that we are reconsidering). - void StartReconsider(const GURL& url, const net::ProxyInfo& proxy_info) { - proxy_info_ = proxy_info; - StartRequest(url, &net::ProxyService::ReconsiderProxyAfterError); - } - - // Start the request. Return once ProxyService::GetProxyForURL() or - // ProxyService::ReconsiderProxyAfterError() returns. - void StartRequest(const GURL& url, RequestMethod method) { - DCHECK(MessageLoop::current() != io_message_loop_); - io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &ResultFuture::DoStartRequest, url, method)); - started_.Wait(); - } - - void StartResetConfigService( - net::ProxyConfigService* new_proxy_config_service) { - DCHECK(MessageLoop::current() != io_message_loop_); - io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &ResultFuture::DoResetConfigService, new_proxy_config_service)); - started_.Wait(); - } - - // Called on |io_message_loop_|. - void DoStartRequest(const GURL& url, RequestMethod method) { - DCHECK(MessageLoop::current() == io_message_loop_); - int rv = (service_->*method)(url, &proxy_info_, &callback_, &request_); - if (rv != net::ERR_IO_PENDING) { - // Completed synchronously. - OnCompletion(rv); + callback->Run(rv); } - started_.Signal(); - } - - // Called on |io_message_loop_|. - void DoResetConfigService(net::ProxyConfigService* new_proxy_config_service) { - DCHECK(MessageLoop::current() == io_message_loop_); - service_->ResetConfigService(new_proxy_config_service); - started_.Signal(); - OnCompletion(0); - } - - // Called on |io_message_loop_|. - void DoCancel() { - DCHECK(MessageLoop::current() == io_message_loop_); - if (!did_complete_) - service_->CancelPacRequest(request_); - cancelled_.Signal(); - } - // Called on |io_message_loop_|. - void OnCompletion(int result) { - DCHECK(MessageLoop::current() == io_message_loop_); - DCHECK(!did_complete_); - did_complete_ = true; - result_code_ = result; - request_ = NULL; - completion_.Signal(); - } - - // The message loop where the ProxyService lives. - MessageLoop* io_message_loop_; - - // The proxy service that started this request. - net::ProxyService* service_; - - // The in-progress request. - net::ProxyService::PacRequest* request_; - - net::CompletionCallbackImpl<ResultFuture> callback_; - base::WaitableEvent completion_; - base::WaitableEvent cancelled_; - base::WaitableEvent started_; - bool did_complete_; - - // Results from the request. - int result_code_; - net::ProxyInfo proxy_info_; -}; - -// Wraps a ProxyService running on its own IO thread. -class ProxyServiceWithFutures { - public: - ProxyServiceWithFutures(net::ProxyConfigService* config_service, - net::ProxyResolver* resolver) - : io_thread_("IO_Thread"), - io_thread_state_(new IOThreadState) { - base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; - io_thread_.StartWithOptions(options); - - // Initialize state that lives on |io_thread_|. - io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - io_thread_state_.get(), &IOThreadState::DoInit, - config_service, resolver)); - io_thread_state_->event.Wait(); - } - - ~ProxyServiceWithFutures() { - // Destroy state that lives on |io_thread_|. - io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - io_thread_state_.get(), &IOThreadState::DoDestroy)); - io_thread_state_->event.Wait(); - } - - // Start the request on |io_thread_|, and return a handle that can be - // used to access the results. The caller is responsible for freeing - // the ResultFuture. - void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) { - *result = new ResultFuture(io_thread_.message_loop(), - io_thread_state_->service); - (*result)->StartResolve(url); - } - - // Same as above, but for "ReconsiderProxyAfterError()". - void ReconsiderProxyAfterError(scoped_refptr<ResultFuture>* result, - const GURL& url, - const net::ProxyInfo& proxy_info) { - *result = new ResultFuture(io_thread_.message_loop(), - io_thread_state_->service); - (*result)->StartReconsider(url, proxy_info); - } - - void ResetConfigService(scoped_refptr<ResultFuture>* result, - net::ProxyConfigService* new_proxy_config_service) { - *result = new ResultFuture(io_thread_.message_loop(), - io_thread_state_->service); - (*result)->StartResetConfigService(new_proxy_config_service); - } - - void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) { - io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - io_thread_state_.get(), &IOThreadState::DoSetProxyScriptFetcher, - proxy_script_fetcher)); - io_thread_state_->event.Wait(); - } - - private: - // Class that encapsulates the state living on IO thread. It needs to be - // ref-counted for posting tasks. - class IOThreadState : public base::RefCountedThreadSafe<IOThreadState> { - public: - IOThreadState() : event(false, false), service(NULL) {} - - void DoInit(net::ProxyConfigService* config_service, - net::ProxyResolver* resolver) { - service = new net::ProxyService(config_service, resolver); - event.Signal(); - } - - void DoDestroy() { - delete service; - service = NULL; - event.Signal(); - } - - void DoSetProxyScriptFetcher( - net::ProxyScriptFetcher* proxy_script_fetcher) { - service->SetProxyScriptFetcher(proxy_script_fetcher); - event.Signal(); - } - - base::WaitableEvent event; - net::ProxyService* service; + private: + MockAsyncProxyResolverBase* resolver_; + const GURL url_; + net::ProxyInfo* results_; + net::CompletionCallback* callback_; + MessageLoop* origin_loop_; }; - base::Thread io_thread_; - scoped_refptr<IOThreadState> io_thread_state_; // Lives on |io_thread_|. -}; + typedef std::vector<scoped_refptr<Request> > RequestsList; -// Wrapper around ProxyServiceWithFutures to do one request at a time. -class SyncProxyService { - public: - SyncProxyService(net::ProxyConfigService* config_service, - net::ProxyResolver* resolver) - : service_(config_service, resolver) { - } + // ProxyResolver implementation: + virtual int GetProxyForURL(const GURL& url, + net::ProxyInfo* results, + net::CompletionCallback* callback, + RequestHandle* request_handle) { + scoped_refptr<Request> request = new Request(this, url, results, callback); + pending_requests_.push_back(request); - int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) { - scoped_refptr<ResultFuture> result; - service_.ResolveProxy(&result, url); - *proxy_info = result->GetProxyInfo(); - return result->GetResultCode(); - } + if (request_handle) + *request_handle = reinterpret_cast<RequestHandle>(request.get()); - int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) { - scoped_refptr<ResultFuture> result; - service_.ReconsiderProxyAfterError(&result, url, *proxy_info); - *proxy_info = result->GetProxyInfo(); - return result->GetResultCode(); + // Test code completes the request by calling request->CompleteNow(). + return net::ERR_IO_PENDING; } - int ResetConfigService(net::ProxyConfigService* new_proxy_config_service) { - scoped_refptr<ResultFuture> result; - service_.ResetConfigService(&result, new_proxy_config_service); - return result->GetResultCode(); + virtual void CancelRequest(RequestHandle request_handle) { + scoped_refptr<Request> request = reinterpret_cast<Request*>(request_handle); + cancelled_requests_.push_back(request); + RemovePendingRequest(request); } - private: - ProxyServiceWithFutures service_; -}; - -// A ProxyResolver which can be set to block upon reaching GetProxyForURL. -class SyncBlockableProxyResolver : public net::ProxyResolver { - public: - SyncBlockableProxyResolver() - : net::ProxyResolver(false /*expects_pac_bytes*/), - should_block_(false), - unblocked_(true, true), - blocked_(true, false) { + virtual void SetPacScriptByUrlInternal(const GURL& pac_url) { + pac_url_ = pac_url; } - void Block() { - should_block_ = true; - unblocked_.Reset(); + virtual void SetPacScriptByDataInternal(const std::string& bytes) { + pac_bytes_ = bytes; } - void Unblock() { - should_block_ = false; - blocked_.Reset(); - unblocked_.Signal(); + const RequestsList& pending_requests() const { + return pending_requests_; } - void WaitUntilBlocked() { - blocked_.Wait(); + const RequestsList& cancelled_requests() const { + return cancelled_requests_; } - // net::ProxyResolver implementation: - virtual int GetProxyForURL(const GURL& query_url, - net::ProxyInfo* results, - net::CompletionCallback* callback, - RequestHandle* request) { - if (should_block_) { - blocked_.Signal(); - unblocked_.Wait(); - } + const GURL& pac_url() const { + return pac_url_; + } - results->UseNamedProxy(query_url.host()); - return net::OK; + const std::string& pac_bytes() const { + return pac_bytes_; } - virtual void CancelRequest(RequestHandle request) { - NOTREACHED(); + void RemovePendingRequest(Request* request) { + RequestsList::iterator it = std::find( + pending_requests_.begin(), pending_requests_.end(), request); + DCHECK(it != pending_requests_.end()); + pending_requests_.erase(it); } - virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {} + protected: + explicit MockAsyncProxyResolverBase(bool expects_pac_bytes) + : net::ProxyResolver(expects_pac_bytes) {} private: - bool should_block_; - base::WaitableEvent unblocked_; - base::WaitableEvent blocked_; -}; - -class BlockableProxyResolver : public net::SingleThreadedProxyResolver { - public: - BlockableProxyResolver() - : net::SingleThreadedProxyResolver(new SyncBlockableProxyResolver) { - x = reinterpret_cast<SyncBlockableProxyResolver*>(resolver()); - } - - // TODO(eroman): cleanup. - SyncBlockableProxyResolver* x; + RequestsList pending_requests_; + RequestsList cancelled_requests_; + GURL pac_url_; + std::string pac_bytes_; }; -// A mock ProxyResolverWithoutFetch which concatenates the query's host with -// the last download PAC contents. This way the result describes what the last -// downloaded PAC script's contents were, in addition to the query url itself. -class SyncMockProxyResolverWithoutFetch : public net::ProxyResolver { +class MockAsyncProxyResolver : public MockAsyncProxyResolverBase { public: - SyncMockProxyResolverWithoutFetch() - : net::ProxyResolver(true /*expects_pac_bytes*/), - last_pac_contents_("NONE") {} - - // net::ProxyResolver implementation: - virtual int GetProxyForURL(const GURL& query_url, - net::ProxyInfo* results, - net::CompletionCallback* callback, - RequestHandle* request) { - results->UseNamedProxy(last_pac_contents_ + "." + query_url.host()); - return net::OK; - } - - virtual void SetPacScriptByDataInternal(const std::string& bytes) { - last_pac_contents_ = bytes; - } - - virtual void CancelRequest(RequestHandle request) { - NOTREACHED(); - } - - private: - std::string last_pac_contents_; + MockAsyncProxyResolver() + : MockAsyncProxyResolverBase(false /*expects_pac_bytes*/) {} }; -class MockProxyResolverWithoutFetch : public net::SingleThreadedProxyResolver { +class MockAsyncProxyResolverExpectsBytes : public MockAsyncProxyResolverBase { public: - MockProxyResolverWithoutFetch() - : net::SingleThreadedProxyResolver( - new SyncMockProxyResolverWithoutFetch) { - x = reinterpret_cast<SyncMockProxyResolverWithoutFetch*>(resolver()); - } - - // TODO(eroman): cleanup. - SyncMockProxyResolverWithoutFetch* x; + MockAsyncProxyResolverExpectsBytes() + : MockAsyncProxyResolverBase(true /*expects_pac_bytes*/) {} }; - } // namespace // A mock ProxyScriptFetcher. No result will be returned to the fetch client // until we call NotifyFetchCompletion() to set the results. class MockProxyScriptFetcher : public net::ProxyScriptFetcher { public: - MockProxyScriptFetcher() : pending_request_loop_(NULL), - pending_request_callback_(NULL), pending_request_bytes_(NULL) {} + MockProxyScriptFetcher() + : pending_request_callback_(NULL), pending_request_bytes_(NULL) { + } // net::ProxyScriptFetcher implementation. - virtual void Fetch(const GURL& url, std::string* bytes, + virtual void Fetch(const GURL& url, + std::string* bytes, net::CompletionCallback* callback) { - DCHECK(!HasPendingRequest()); + DCHECK(!has_pending_request()); // Save the caller's information, and have them wait. - pending_request_loop_ = MessageLoop::current(); pending_request_url_ = url; pending_request_callback_ = callback; pending_request_bytes_ = bytes; } void NotifyFetchCompletion(int result, const std::string& bytes) { - DCHECK(HasPendingRequest()); - pending_request_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &MockProxyScriptFetcher::DoNotifyFetchCompletion, result, bytes)); + DCHECK(has_pending_request()); + *pending_request_bytes_ = bytes; + pending_request_callback_->Run(result); } virtual void Cancel() {} - private: - // Runs on |pending_request_loop_|. - void DoNotifyFetchCompletion(int result, const std::string& bytes) { - DCHECK(HasPendingRequest()); - *pending_request_bytes_ = bytes; - pending_request_callback_->Run(result); + const GURL& pending_request_url() const { + return pending_request_url_; } - bool HasPendingRequest() const { - return pending_request_loop_ != NULL; + bool has_pending_request() const { + return pending_request_callback_ != NULL; } - MessageLoop* pending_request_loop_; + private: GURL pending_request_url_; net::CompletionCallback* pending_request_callback_; std::string* pending_request_bytes_; @@ -508,14 +201,17 @@ void RunnableMethodTraits<MockProxyScriptFetcher>::ReleaseCallee( MockProxyScriptFetcher* remover) {} TEST(ProxyServiceTest, Direct) { - SyncProxyService service(new MockProxyConfigService, - new MockProxyResolver); + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; + net::ProxyService service(new MockProxyConfigService, resolver); GURL url("http://www.google.com/"); net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_TRUE(resolver->pending_requests().empty()); + EXPECT_TRUE(info.is_direct()); } @@ -523,17 +219,26 @@ TEST(ProxyServiceTest, PAC) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - MockProxyResolver* resolver = new MockProxyResolver; - resolver->x->info.UseNamedProxy("foopy"); - resolver->x->info_predicate_query_host = "www.google.com"; + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - SyncProxyService service(config_service, resolver); + net::ProxyService service(config_service, resolver); GURL url("http://www.google.com/"); net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(url, &info, &callback, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + // Set the result in proxy resolver. + resolver->pending_requests()[0]->results()->UseNamedProxy("foopy"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + EXPECT_EQ(net::OK, callback.WaitForResult()); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); } @@ -541,59 +246,86 @@ TEST(ProxyServiceTest, PAC) { TEST(ProxyServiceTest, PAC_FailoverToDirect) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - MockProxyResolver* resolver = new MockProxyResolver; - resolver->x->info.UseNamedProxy("foopy:8080"); - resolver->x->info_predicate_query_host = "www.google.com"; - - SyncProxyService service(config_service, resolver); + net::ProxyService service(config_service, resolver); GURL url("http://www.google.com/"); net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback1; + int rv = service.ResolveProxy(url, &info, &callback1, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + // Set the result in proxy resolver. + resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + EXPECT_EQ(net::OK, callback1.WaitForResult()); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); // Now, imagine that connecting to foopy:8080 fails. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback2; + rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } -TEST(ProxyServiceTest, PAC_FailsToDownload) { - // Test what happens when we fail to download the PAC URL. +TEST(ProxyServiceTest, ProxyResolverFails) { + // Test what happens when the ProxyResolver fails (this could represent + // a failure to download the PAC script in the case of ProxyResolvers which + // do the fetch internally.) MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - MockProxyResolver* resolver = new MockProxyResolver; - resolver->x->info.UseNamedProxy("foopy:8080"); - resolver->x->info_predicate_query_host = "www.google.com"; - resolver->x->fail_get_proxy_for_url = true; + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - SyncProxyService service(config_service, resolver); + net::ProxyService service(config_service, resolver); - // The first resolve fails in the MockProxyResolver. + // Start first resolve request. GURL url("http://www.google.com/"); net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::ERR_FAILED); + TestCompletionCallback callback1; + int rv = service.ResolveProxy(url, &info, &callback1, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + // Fail the first resolve request in MockAsyncProxyResolver. + resolver->pending_requests()[0]->CompleteNow(net::ERR_FAILED); + + EXPECT_EQ(net::ERR_FAILED, callback1.WaitForResult()); // The second resolve request will automatically select direct connect, // because it has cached the configuration as being bad. - rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback2; + rv = service.ResolveProxy(url, &info, &callback2, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); - - resolver->x->fail_get_proxy_for_url = false; - resolver->x->info.UseNamedProxy("foopy_valid:8080"); + EXPECT_TRUE(resolver->pending_requests().empty()); // But, if that fails, then we should give the proxy config another shot // since we have never tried it with this URL before. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback3; + rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + // Set the result in proxy resolver. + resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + EXPECT_EQ(net::OK, callback3.WaitForResult()); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); } @@ -605,56 +337,73 @@ TEST(ProxyServiceTest, ProxyFallback) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - MockProxyResolver* resolver = new MockProxyResolver; - resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); - resolver->x->info_predicate_query_host = "www.google.com"; - resolver->x->fail_get_proxy_for_url = false; + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - SyncProxyService service(config_service, resolver); + net::ProxyService service(config_service, resolver); GURL url("http://www.google.com/"); // Get the proxy information. net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info.is_direct()); + TestCompletionCallback callback1; + int rv = service.ResolveProxy(url, &info, &callback1, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + // Set the result in proxy resolver. + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy1:8080;foopy2:9090"); + resolver->pending_requests()[0]->CompleteNow(net::OK); // The first item is valid. + EXPECT_EQ(net::OK, callback1.WaitForResult()); + EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); // Fake an error on the proxy. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback2; + rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); + EXPECT_EQ(net::OK, rv); // The second proxy should be specified. EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); - // Create a new resolver that returns 3 proxies. The second one is already - // known to be bad. - config_service->config.pac_url = GURL("http://foopy/proxy.pac"); - resolver->x->info.UseNamedProxy("foopy3:7070;foopy1:8080;foopy2:9090"); - resolver->x->info_predicate_query_host = "www.google.com"; - resolver->x->fail_get_proxy_for_url = false; + TestCompletionCallback callback3; + rv = service.ResolveProxy(url, &info, &callback3, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); - rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); + // Set the result in proxy resolver -- the second result is already known + // to be bad. + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy3:7070;foopy1:8080;foopy2:9090"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + EXPECT_EQ(net::OK, callback3.WaitForResult()); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); // We fake another error. It should now try the third one. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback4; + rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); // Fake another error, the last proxy is gone, the list should now be empty. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); // We try direct. + TestCompletionCallback callback5; + rv = service.ReconsiderProxyAfterError(url, &info, &callback5, NULL); + EXPECT_EQ(net::OK, rv); // We try direct. EXPECT_TRUE(info.is_direct()); // If it fails again, we don't have anything else to try. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::ERR_FAILED); // We try direct. + TestCompletionCallback callback6; + rv = service.ReconsiderProxyAfterError(url, &info, &callback6, NULL); + EXPECT_EQ(net::ERR_FAILED, rv); // TODO(nsylvain): Test that the proxy can be retried after the delay. } @@ -665,46 +414,76 @@ TEST(ProxyServiceTest, ProxyFallback_NewSettings) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - MockProxyResolver* resolver = new MockProxyResolver; - resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); - resolver->x->info_predicate_query_host = "www.google.com"; - resolver->x->fail_get_proxy_for_url = false; + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - SyncProxyService service(config_service, resolver); + net::ProxyService service(config_service, resolver); GURL url("http://www.google.com/"); // Get the proxy information. net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info.is_direct()); + TestCompletionCallback callback1; + int rv = service.ResolveProxy(url, &info, &callback1, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + // Set the result in proxy resolver. + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy1:8080;foopy2:9090"); + resolver->pending_requests()[0]->CompleteNow(net::OK); // The first item is valid. + EXPECT_EQ(net::OK, callback1.WaitForResult()); + EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); // Fake an error on the proxy, and also a new configuration on the proxy. config_service->config = net::ProxyConfig(); config_service->config.pac_url = GURL("http://foopy-new/proxy.pac"); - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback2; + rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy-new/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy1:8080;foopy2:9090"); + resolver->pending_requests()[0]->CompleteNow(net::OK); // The first proxy is still there since the configuration changed. + EXPECT_EQ(net::OK, callback2.WaitForResult()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); // We fake another error. It should now ignore the first one. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback3; + rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); // We simulate a new configuration. config_service->config = net::ProxyConfig(); config_service->config.pac_url = GURL("http://foopy-new2/proxy.pac"); - // We fake anothe error. It should go back to the first proxy. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + // We fake another error. It should go back to the first proxy. + TestCompletionCallback callback4; + rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy1:8080;foopy2:9090"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + EXPECT_EQ(net::OK, callback4.WaitForResult()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); } @@ -714,27 +493,35 @@ TEST(ProxyServiceTest, ProxyFallback_BadConfig) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - MockProxyResolver* resolver = new MockProxyResolver; - resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); - resolver->x->info_predicate_query_host = "www.google.com"; - resolver->x->fail_get_proxy_for_url = false; + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - SyncProxyService service(config_service, resolver); + net::ProxyService service(config_service, resolver); GURL url("http://www.google.com/"); // Get the proxy information. net::ProxyInfo info; - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info.is_direct()); + TestCompletionCallback callback1; + int rv = service.ResolveProxy(url, &info, &callback1, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy1:8080;foopy2:9090"); + resolver->pending_requests()[0]->CompleteNow(net::OK); // The first item is valid. + EXPECT_EQ(net::OK, callback1.WaitForResult()); + EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); // Fake a proxy error. - rv = service.ReconsiderProxyAfterError(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback2; + rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); + EXPECT_EQ(net::OK, rv); // The first proxy is ignored, and the second one is selected. EXPECT_FALSE(info.is_direct()); @@ -742,31 +529,46 @@ TEST(ProxyServiceTest, ProxyFallback_BadConfig) { // Fake a PAC failure. net::ProxyInfo info2; - resolver->x->fail_get_proxy_for_url = true; - rv = service.ResolveProxy(url, &info2); - EXPECT_EQ(rv, net::ERR_FAILED); + TestCompletionCallback callback3; + rv = service.ResolveProxy(url, &info2, &callback3, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + resolver->pending_requests()[0]->CompleteNow(net::ERR_FAILED); // No proxy servers are returned. It's a direct connection. + EXPECT_EQ(net::ERR_FAILED, callback3.WaitForResult()); EXPECT_TRUE(info2.is_direct()); - // The PAC is now fixed and will return a proxy server. + // The PAC will now be fixed and will return a proxy server. // It should also clear the list of bad proxies. - resolver->x->fail_get_proxy_for_url = false; // Try to resolve, it will still return "direct" because we have no reason // to check the config since everything works. net::ProxyInfo info3; - rv = service.ResolveProxy(url, &info3); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback4; + rv = service.ResolveProxy(url, &info3, &callback4, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info3.is_direct()); // But if the direct connection fails, we check if the ProxyInfo tried to // resolve the proxy before, and if not (like in this case), we give the // PAC another try. - rv = service.ReconsiderProxyAfterError(url, &info3); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback5; + rv = service.ReconsiderProxyAfterError(url, &info3, &callback5, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url, resolver->pending_requests()[0]->url()); + + resolver->pending_requests()[0]->results()->UseNamedProxy( + "foopy1:8080;foopy2:9090"); + resolver->pending_requests()[0]->CompleteNow(net::OK); // The first proxy is still there since the list of bad proxies got cleared. + EXPECT_EQ(net::OK, callback5.WaitForResult()); EXPECT_FALSE(info3.is_direct()); EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); } @@ -781,21 +583,23 @@ TEST(ProxyServiceTest, ProxyBypassList) { config.proxy_bypass_local_names = true; { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver()); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver()); GURL url("http://www.google.com/"); // Get the proxy information. - int rv = service.ResolveProxy(url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_FALSE(info.is_direct()); } { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver()); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver()); GURL test_url("local"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } @@ -803,11 +607,12 @@ TEST(ProxyServiceTest, ProxyBypassList) { config.proxy_bypass.push_back("*.org"); config.proxy_bypass_local_names = true; { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); GURL test_url("http://www.webkit.org"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } @@ -816,11 +621,12 @@ TEST(ProxyServiceTest, ProxyBypassList) { config.proxy_bypass.push_back("7*"); config.proxy_bypass_local_names = true; { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); GURL test_url("http://74.125.19.147"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } @@ -828,11 +634,12 @@ TEST(ProxyServiceTest, ProxyBypassList) { config.proxy_bypass.push_back("*.org"); config.proxy_bypass_local_names = true; { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); GURL test_url("http://www.msn.com"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_FALSE(info.is_direct()); } @@ -840,11 +647,12 @@ TEST(ProxyServiceTest, ProxyBypassList) { config.proxy_bypass.push_back("*.MSN.COM"); config.proxy_bypass_local_names = true; { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); GURL test_url("http://www.msnbc.msn.com"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } @@ -852,11 +660,12 @@ TEST(ProxyServiceTest, ProxyBypassList) { config.proxy_bypass.push_back("*.msn.com"); config.proxy_bypass_local_names = true; { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); GURL test_url("HTTP://WWW.MSNBC.MSN.COM"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } } @@ -872,24 +681,27 @@ TEST(ProxyServiceTest, ProxyBypassListWithPorts) { config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.example.com:99"); { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); { GURL test_url("http://www.example.com:99"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } { GURL test_url("http://www.example.com:100"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_FALSE(info.is_direct()); } { GURL test_url("http://www.example.com"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_FALSE(info.is_direct()); } } @@ -897,22 +709,24 @@ TEST(ProxyServiceTest, ProxyBypassListWithPorts) { config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.example.com:80"); { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); GURL test_url("http://www.example.com"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } config.proxy_bypass.clear(); config.proxy_bypass.push_back("*.example.com"); { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); GURL test_url("http://www.example.com:99"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } @@ -920,18 +734,20 @@ TEST(ProxyServiceTest, ProxyBypassListWithPorts) { config.proxy_bypass.clear(); config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99"); { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); { GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } { GURL test_url("http://[3ffe:2a00:100:7031::1]/"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_FALSE(info.is_direct()); } } @@ -942,18 +758,20 @@ TEST(ProxyServiceTest, ProxyBypassListWithPorts) { config.proxy_bypass.clear(); config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]"); { - SyncProxyService service(new MockProxyConfigService(config), - new MockProxyResolver); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); { GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } { GURL test_url("http://[3ffe:2a00:100:7031::1]/"); - int rv = service.ResolveProxy(test_url, &info); - EXPECT_EQ(rv, net::OK); + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_TRUE(info.is_direct()); } } @@ -963,43 +781,51 @@ TEST(ProxyServiceTest, PerProtocolProxyTests) { net::ProxyConfig config; config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080"); config.auto_detect = false; - - SyncProxyService service1(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url1("http://www.msn.com"); - net::ProxyInfo info1; - int rv = service1.ResolveProxy(test_url1, &info1); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info1.is_direct()); - EXPECT_EQ("foopy1:8080", info1.proxy_server().ToURI()); - - SyncProxyService service2(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url2("ftp://ftp.google.com"); - net::ProxyInfo info2; - rv = service2.ResolveProxy(test_url2, &info2); - EXPECT_EQ(rv, net::OK); - EXPECT_TRUE(info2.is_direct()); - EXPECT_EQ("direct://", info2.proxy_server().ToURI()); - - SyncProxyService service3(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url3("https://webbranch.techcu.com"); - net::ProxyInfo info3; - rv = service3.ResolveProxy(test_url3, &info3); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info3.is_direct()); - EXPECT_EQ("foopy2:8080", info3.proxy_server().ToURI()); - - config.proxy_rules.ParseFromString("foopy1:8080"); - SyncProxyService service4(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url4("www.microsoft.com"); - net::ProxyInfo info4; - rv = service4.ResolveProxy(test_url4, &info4); - EXPECT_EQ(rv, net::OK); - EXPECT_FALSE(info4.is_direct()); - EXPECT_EQ("foopy1:8080", info4.proxy_server().ToURI()); + { + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("http://www.msn.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); + } + { + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("ftp://ftp.google.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_TRUE(info.is_direct()); + EXPECT_EQ("direct://", info.proxy_server().ToURI()); + } + { + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("https://webbranch.techcu.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); + } + { + config.proxy_rules.ParseFromString("foopy1:8080"); + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("www.microsoft.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); + } } // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries @@ -1011,181 +837,189 @@ TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, config.proxy_rules.type); - SyncProxyService service1(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url1("http://www.msn.com"); - net::ProxyInfo info1; - int rv = service1.ResolveProxy(test_url1, &info1); - EXPECT_EQ(net::OK, rv); - EXPECT_FALSE(info1.is_direct()); - EXPECT_EQ("foopy1:8080", info1.proxy_server().ToURI()); - - SyncProxyService service2(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url2("ftp://ftp.google.com"); - net::ProxyInfo info2; - rv = service2.ResolveProxy(test_url2, &info2); - EXPECT_EQ(net::OK, rv); - EXPECT_FALSE(info2.is_direct()); - EXPECT_EQ("socks4://foopy2:1080", info2.proxy_server().ToURI()); - - SyncProxyService service3(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url3("https://webbranch.techcu.com"); - net::ProxyInfo info3; - rv = service3.ResolveProxy(test_url3, &info3); - EXPECT_EQ(net::OK, rv); - EXPECT_FALSE(info3.is_direct()); - EXPECT_EQ("socks4://foopy2:1080", info3.proxy_server().ToURI()); - - SyncProxyService service4(new MockProxyConfigService(config), - new MockProxyResolver); - GURL test_url4("www.microsoft.com"); - net::ProxyInfo info4; - rv = service4.ResolveProxy(test_url4, &info4); - EXPECT_EQ(net::OK, rv); - EXPECT_FALSE(info4.is_direct()); - EXPECT_EQ("socks4://foopy2:1080", info4.proxy_server().ToURI()); + { + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("http://www.msn.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); + } + { + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("ftp://ftp.google.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); + } + { + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("https://webbranch.techcu.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); + } + { + net::ProxyService service(new MockProxyConfigService(config), + new MockAsyncProxyResolver); + GURL test_url("www.microsoft.com"); + net::ProxyInfo info; + TestCompletionCallback callback; + int rv = service.ResolveProxy(test_url, &info, &callback, NULL); + EXPECT_EQ(net::OK, rv); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); + } } -// Test cancellation of a queued request. -TEST(ProxyServiceTest, CancelQueuedRequest) { +// Test cancellation of an in-progress request. +TEST(ProxyServiceTest, CancelInProgressRequest) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - BlockableProxyResolver* resolver = new BlockableProxyResolver; - - ProxyServiceWithFutures service(config_service, resolver); + MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - // Cause requests to pile up, by having them block in the PAC thread. - resolver->x->Block(); + net::ProxyService service(config_service, resolver); // Start 3 requests. - scoped_refptr<ResultFuture> result1; - service.ResolveProxy(&result1, GURL("http://request1")); - scoped_refptr<ResultFuture> result2; - service.ResolveProxy(&result2, GURL("http://request2")); + net::ProxyInfo info1; + TestCompletionCallback callback1; + int rv = service.ResolveProxy( + GURL("http://request1"), &info1, &callback1, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); - scoped_refptr<ResultFuture> result3; - service.ResolveProxy(&result3, GURL("http://request3")); + net::ProxyInfo info2; + TestCompletionCallback callback2; + net::ProxyService::PacRequest* request2; + rv = service.ResolveProxy( + GURL("http://request2"), &info2, &callback2, &request2); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + ASSERT_EQ(2u, resolver->pending_requests().size()); + EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); - // Wait until the first request has become blocked in the PAC thread. - resolver->x->WaitUntilBlocked(); + net::ProxyInfo info3; + TestCompletionCallback callback3; + rv = service.ResolveProxy( + GURL("http://request3"), &info3, &callback3, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + ASSERT_EQ(3u, resolver->pending_requests().size()); + EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); // Cancel the second request - result2->Cancel(); + service.CancelPacRequest(request2); - // Unblock the PAC thread. - resolver->x->Unblock(); + ASSERT_EQ(2u, resolver->pending_requests().size()); + EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); + EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url()); - // Wait for the final request to complete. - result3->WaitUntilCompleted(); + // Complete the two un-cancelled requests. + // We complete the last one first, just to mix it up a bit. + resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80"); + resolver->pending_requests()[1]->CompleteNow(net::OK); - // Verify that requests ran as expected. + resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); - EXPECT_TRUE(result1->IsCompleted()); - EXPECT_EQ(net::OK, result1->GetResultCode()); - EXPECT_EQ("request1:80", result1->GetProxyInfo().proxy_server().ToURI()); + // Complete and verify that requests ran as expected. + EXPECT_EQ(net::OK, callback1.WaitForResult()); + EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); - EXPECT_FALSE(result2->IsCompleted()); // Cancelled. + EXPECT_FALSE(callback2.have_result()); // Cancelled. + ASSERT_EQ(1u, resolver->cancelled_requests().size()); + EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url()); - EXPECT_TRUE(result3->IsCompleted()); - EXPECT_EQ(net::OK, result3->GetResultCode()); - EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); + EXPECT_EQ(net::OK, callback3.WaitForResult()); + EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); } -// Test cancellation of an in-progress request. -TEST(ProxyServiceTest, CancelInprogressRequest) { +// Test the initial PAC download for ProxyResolverWithoutFetch. +TEST(ProxyServiceTest, InitialPACScriptDownload) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - BlockableProxyResolver* resolver = new BlockableProxyResolver; + MockAsyncProxyResolverExpectsBytes* resolver = + new MockAsyncProxyResolverExpectsBytes; - ProxyServiceWithFutures service(config_service, resolver); + net::ProxyService service(config_service, resolver); - // Cause requests to pile up, by having them block in the PAC thread. - resolver->x->Block(); + MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; + service.SetProxyScriptFetcher(fetcher); // Start 3 requests. - scoped_refptr<ResultFuture> result1; - service.ResolveProxy(&result1, GURL("http://request1")); - - scoped_refptr<ResultFuture> result2; - service.ResolveProxy(&result2, GURL("http://request2")); - - scoped_refptr<ResultFuture> result3; - service.ResolveProxy(&result3, GURL("http://request3")); - // Wait until the first request has become blocked in the PAC thread. - resolver->x->WaitUntilBlocked(); - - // Cancel the first request - result1->Cancel(); - - // Unblock the PAC thread. - resolver->x->Unblock(); - - // Wait for the final request to complete. - result3->WaitUntilCompleted(); + net::ProxyInfo info1; + TestCompletionCallback callback1; + int rv = service.ResolveProxy( + GURL("http://request1"), &info1, &callback1, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); - // Verify that requests ran as expected. + // The first request should have triggered download of PAC script. + EXPECT_TRUE(fetcher->has_pending_request()); + EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); - EXPECT_FALSE(result1->IsCompleted()); // Cancelled. + net::ProxyInfo info2; + TestCompletionCallback callback2; + rv = service.ResolveProxy( + GURL("http://request2"), &info2, &callback2, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); - EXPECT_TRUE(result2->IsCompleted()); - EXPECT_EQ(net::OK, result2->GetResultCode()); - EXPECT_EQ("request2:80", result2->GetProxyInfo().proxy_server().ToURI()); + net::ProxyInfo info3; + TestCompletionCallback callback3; + rv = service.ResolveProxy( + GURL("http://request3"), &info3, &callback3, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); - EXPECT_TRUE(result3->IsCompleted()); - EXPECT_EQ(net::OK, result3->GetResultCode()); - EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); -} + // Nothing has been sent to the resolver yet. + EXPECT_TRUE(resolver->pending_requests().empty()); -// Test the initial PAC download for ProxyResolverWithoutFetch. -TEST(ProxyServiceTest, InitialPACScriptDownload) { - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); + // At this point the ProxyService should be waiting for the + // ProxyScriptFetcher to invoke its completion callback, notifying it of + // PAC script download completion. + fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); - MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; + // Now that the PAC script is downloaded, everything should have been sent + // over to the proxy resolver. + EXPECT_EQ("pac-v1", resolver->pac_bytes()); + ASSERT_EQ(3u, resolver->pending_requests().size()); + EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); + EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); + EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); - ProxyServiceWithFutures service(config_service, resolver); + // Complete all the requests (in some order). + // Note that as we complete requests, they shift up in |pending_requests()|. - MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; - service.SetProxyScriptFetcher(fetcher); + resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80"); + resolver->pending_requests()[2]->CompleteNow(net::OK); - // Start 3 requests. - scoped_refptr<ResultFuture> result1; - service.ResolveProxy(&result1, GURL("http://request1")); + resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); - scoped_refptr<ResultFuture> result2; - service.ResolveProxy(&result2, GURL("http://request2")); + resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); - scoped_refptr<ResultFuture> result3; - service.ResolveProxy(&result3, GURL("http://request3")); + // Complete and verify that requests ran as expected. + EXPECT_EQ(net::OK, callback1.WaitForResult()); + EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); - // At this point the ProxyService should be waiting for the - // ProxyScriptFetcher to invoke its completion callback, notifying it of - // PAC script download completion. - fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); + EXPECT_EQ(net::OK, callback2.WaitForResult()); + EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); - // Complete all the requests. - result3->WaitUntilCompleted(); - - EXPECT_TRUE(result1->IsCompleted()); - EXPECT_EQ(net::OK, result1->GetResultCode()); - EXPECT_EQ("pac-v1.request1:80", - result1->GetProxyInfo().proxy_server().ToURI()); - - EXPECT_TRUE(result2->IsCompleted()); - EXPECT_EQ(net::OK, result2->GetResultCode()); - EXPECT_EQ("pac-v1.request2:80", - result2->GetProxyInfo().proxy_server().ToURI()); - - EXPECT_TRUE(result3->IsCompleted()); - EXPECT_EQ(net::OK, result3->GetResultCode()); - EXPECT_EQ("pac-v1.request3:80", - result3->GetProxyInfo().proxy_server().ToURI()); + EXPECT_EQ(net::OK, callback3.WaitForResult()); + EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); } // Test cancellation of a request, while the PAC script is being fetched. @@ -1193,61 +1027,90 @@ TEST(ProxyServiceTest, CancelWhilePACFetching) { MockProxyConfigService* config_service = new MockProxyConfigService("http://foopy/proxy.pac"); - MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; + MockAsyncProxyResolverExpectsBytes* resolver = + new MockAsyncProxyResolverExpectsBytes; - ProxyServiceWithFutures service(config_service, resolver); + net::ProxyService service(config_service, resolver); MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; service.SetProxyScriptFetcher(fetcher); // Start 3 requests. - scoped_refptr<ResultFuture> result1; - service.ResolveProxy(&result1, GURL("http://request1")); + net::ProxyInfo info1; + TestCompletionCallback callback1; + net::ProxyService::PacRequest* request1; + int rv = service.ResolveProxy( + GURL("http://request1"), &info1, &callback1, &request1); + EXPECT_EQ(net::ERR_IO_PENDING, rv); - scoped_refptr<ResultFuture> result2; - service.ResolveProxy(&result2, GURL("http://request2")); + // The first request should have triggered download of PAC script. + EXPECT_TRUE(fetcher->has_pending_request()); + EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); - scoped_refptr<ResultFuture> result3; - service.ResolveProxy(&result3, GURL("http://request3")); + net::ProxyInfo info2; + TestCompletionCallback callback2; + net::ProxyService::PacRequest* request2; + rv = service.ResolveProxy( + GURL("http://request2"), &info2, &callback2, &request2); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + net::ProxyInfo info3; + TestCompletionCallback callback3; + rv = service.ResolveProxy( + GURL("http://request3"), &info3, &callback3, NULL); + EXPECT_EQ(net::ERR_IO_PENDING, rv); + + // Nothing has been sent to the resolver yet. + EXPECT_TRUE(resolver->pending_requests().empty()); // Cancel the first 2 requests. - result1->Cancel(); - result2->Cancel(); + service.CancelPacRequest(request1); + service.CancelPacRequest(request2); // At this point the ProxyService should be waiting for the // ProxyScriptFetcher to invoke its completion callback, notifying it of // PAC script download completion. fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); + // Now that the PAC script is downloaded, everything should have been sent + // over to the proxy resolver. + EXPECT_EQ("pac-v1", resolver->pac_bytes()); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url()); + // Complete all the requests. - result3->WaitUntilCompleted(); + resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + EXPECT_EQ(net::OK, callback3.WaitForResult()); + EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); - EXPECT_FALSE(result1->IsCompleted()); // Cancelled. - EXPECT_FALSE(result2->IsCompleted()); // Cancelled. + EXPECT_TRUE(resolver->cancelled_requests().empty()); - EXPECT_TRUE(result3->IsCompleted()); - EXPECT_EQ(net::OK, result3->GetResultCode()); - EXPECT_EQ("pac-v1.request3:80", - result3->GetProxyInfo().proxy_server().ToURI()); + EXPECT_FALSE(callback1.have_result()); // Cancelled. + EXPECT_FALSE(callback2.have_result()); // Cancelled. } TEST(ProxyServiceTest, ResetProxyConfigService) { net::ProxyConfig config1; config1.proxy_rules.ParseFromString("foopy1:8080"); config1.auto_detect = false; - scoped_ptr<SyncProxyService> service( - new SyncProxyService(new MockProxyConfigService(config1), - new MockProxyResolverWithoutFetch)); + net::ProxyService service(new MockProxyConfigService(config1), + new MockAsyncProxyResolverExpectsBytes); net::ProxyInfo info; - service->ResolveProxy(GURL("http://request1"), &info); + TestCompletionCallback callback1; + int rv = service.ResolveProxy( + GURL("http://request1"), &info, &callback1, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); net::ProxyConfig config2; config2.proxy_rules.ParseFromString("foopy2:8080"); config2.auto_detect = false; - int result = service->ResetConfigService(new MockProxyConfigService(config2)); - DCHECK(result == 0); - service->ResolveProxy(GURL("http://request2"), &info); + service.ResetConfigService(new MockProxyConfigService(config2)); + TestCompletionCallback callback2; + rv = service.ResolveProxy(GURL("http://request2"), &info, &callback2, NULL); + EXPECT_EQ(net::OK, rv); EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); } |