diff options
-rw-r--r-- | chrome/browser/net/resolve_proxy_msg_helper_unittest.cc | 408 | ||||
-rw-r--r-- | net/net.gyp | 1 | ||||
-rw-r--r-- | net/proxy/mock_proxy_resolver.h | 1375 | ||||
-rw-r--r-- | net/proxy/proxy_service_unittest.cc | 151 |
4 files changed, 140 insertions, 1795 deletions
diff --git a/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc b/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc index ef016d3..b9974ca 100644 --- a/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc +++ b/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc @@ -6,13 +6,12 @@ #include "base/waitable_event.h" #include "net/base/net_errors.h" +#include "net/proxy/mock_proxy_resolver.h" #include "net/proxy/proxy_config_service.h" -#include "net/proxy/proxy_resolver.h" -#include "net/proxy/single_threaded_proxy_resolver.h" #include "testing/gtest/include/gtest/gtest.h" // This ProxyConfigService always returns "http://pac" as the PAC url to use. -class MockProxyConfigService: public net::ProxyConfigService { +class MockProxyConfigService : public net::ProxyConfigService { public: virtual int GetProxyConfig(net::ProxyConfig* results) { results->pac_url = GURL("http://pac"); @@ -20,232 +19,45 @@ class MockProxyConfigService: public net::ProxyConfigService { } }; -// This PAC resolver always returns the hostname of the query URL as the -// proxy to use. The Block() method will make GetProxyForURL() hang until -// Unblock() is called. -class SyncMockProxyResolver : public net::ProxyResolver { +class MyDelegate : public ResolveProxyMsgHelper::Delegate { public: - SyncMockProxyResolver() : ProxyResolver(false /*expects_pac_bytes*/), - event_(false, false), - is_blocked_(false) { - } - - virtual int GetProxyForURL(const GURL& query_url, - net::ProxyInfo* results, - net::CompletionCallback* callback, - RequestHandle* request) { - if (is_blocked_) - event_.Wait(); - results->UseNamedProxy(query_url.host()); - return net::OK; - } - - virtual void CancelRequest(RequestHandle request) { - NOTREACHED(); - } - - virtual int SetPacScript(const GURL& /*pac_url*/, - const std::string& /*bytes*/, - net::CompletionCallback* /*callback*/) { - return net::OK; - } - - void Block() { - is_blocked_ = true; - event_.Reset(); - } - - void Unblock() { - is_blocked_ = false; - event_.Signal(); - } - - private: - base::WaitableEvent event_; - bool is_blocked_; -}; - -class MockProxyResolver : public net::SingleThreadedProxyResolver { - public: - MockProxyResolver() - : net::SingleThreadedProxyResolver(new SyncMockProxyResolver) { - x = reinterpret_cast<SyncMockProxyResolver*>(resolver()); - } - - // TODO(eroman): cleanup. - SyncMockProxyResolver* x; -}; - -// This struct holds the values that were passed to -// Delegate::OnResolveProxyCompleted(). The caller should use WaitUntilDone() -// to block until the result has been populated. -struct ResultFuture { - public: - ResultFuture() - : reply_msg(NULL), - error_code(0), - started_(false, false), - completed_(false, false) { - } - - // Wait until the request has completed. In other words we have invoked: - // ResolveProxyMsgHelper::Delegate::OnResolveProxyCompleted. - void WaitUntilDone() { - completed_.Wait(); - } - - // Wait until the request has been sent to ResolveProxyMsgHelper. - void WaitUntilStarted() { - started_.Wait(); - } - - bool TimedWaitUntilDone(const base::TimeDelta& max_time) { - return completed_.TimedWait(max_time); - } - - // These fields are only valid after returning from WaitUntilDone(). - IPC::Message* reply_msg; - int error_code; - std::string proxy_list; - - private: - friend class AsyncRequestRunner; - base::WaitableEvent started_; - base::WaitableEvent completed_; -}; - -// This class lives on the io thread. It starts async requests using the -// class under test (ResolveProxyMsgHelper), and signals the result future on -// completion. -class AsyncRequestRunner : public ResolveProxyMsgHelper::Delegate { - public: - AsyncRequestRunner(net::ProxyService* proxy_service) { - resolve_proxy_msg_helper_.reset( - new ResolveProxyMsgHelper(this, proxy_service)); - } - - void Start(ResultFuture* future, const GURL& url, IPC::Message* reply_msg) { - futures_.push_back(future); - resolve_proxy_msg_helper_->Start(url, reply_msg); - - // Notify of request start. - future->started_.Signal(); - } - + struct PendingResult { + PendingResult(IPC::Message* msg, + int error_code, + const std::string& proxy_list) + : msg(msg), error_code(error_code), proxy_list(proxy_list) { + } + + IPC::Message* msg; + int error_code; + std::string proxy_list; + }; + + // ResolveProxyMsgHelper::Delegate implementation: virtual void OnResolveProxyCompleted(IPC::Message* reply_msg, int error_code, const std::string& proxy_list) { - // Update the result future for this request (top of queue), and signal it. - ResultFuture* future = futures_.front(); - futures_.pop_front(); - - future->reply_msg = reply_msg; - future->error_code = error_code; - future->proxy_list = proxy_list; - - // Notify of request completion. - future->completed_.Signal(); - } - - private: - std::deque<ResultFuture*> futures_; - scoped_ptr<ResolveProxyMsgHelper> resolve_proxy_msg_helper_; -}; - -// Helper class to start async requests on an io thread, and return a -// result future. The caller then uses ResultFuture::WaitUntilDone() to -// get at the results. It "bridges" the originating thread with the helper -// io thread. -class RunnerBridge { - public: - RunnerBridge() : io_thread_("io_thread"), done_(false, false) { - // Start an io thread where we will run the async requests. - base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; - io_thread_.StartWithOptions(options); - - // Construct the state that lives on io thread. - io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - this, &RunnerBridge::DoConstruct)); - done_.Wait(); + DCHECK(!pending_result_.get()); + pending_result_.reset(new PendingResult(reply_msg, error_code, proxy_list)); } - // Start an async request on the io thread. - ResultFuture* Start(const GURL& url, IPC::Message* reply_msg) { - ResultFuture* future = new ResultFuture(); + const PendingResult* pending_result() const { return pending_result_.get(); } - io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - async_runner_, &AsyncRequestRunner::Start, future, url, reply_msg)); - - return future; - } - - void DestroyAsyncRunner() { - io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - this, &RunnerBridge::DoDestroyAsyncRunner)); - done_.Wait(); - } - - ~RunnerBridge() { - io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - this, &RunnerBridge::DoDestroy)); - done_.Wait(); - } - - MockProxyResolver* proxy_resolver() { - return proxy_resolver_; - } - - // Called from io thread. - void DoConstruct() { - proxy_resolver_ = new MockProxyResolver(); - proxy_service_ = new net::ProxyService(new MockProxyConfigService(), - proxy_resolver_); - async_runner_ = new AsyncRequestRunner(proxy_service_); - done_.Signal(); - } - - // Called from io thread. - void DoDestroy() { - delete async_runner_; - delete proxy_service_; - done_.Signal(); - } - - // Called from io thread. - void DoDestroyAsyncRunner() { - delete async_runner_; - async_runner_ = NULL; - done_.Signal(); + void clear_pending_result() { + pending_result_.reset(); } private: - base::Thread io_thread_; - base::WaitableEvent done_; - - net::ProxyService* proxy_service_; - MockProxyResolver* proxy_resolver_; // Owned by proxy_service_. - - AsyncRequestRunner* async_runner_; + scoped_ptr<PendingResult> pending_result_; }; -// Avoid the need to have an AddRef / Release -template<> -void RunnableMethodTraits<RunnerBridge>::RetainCallee(RunnerBridge*) {} -template<> -void RunnableMethodTraits<RunnerBridge>::ReleaseCallee(RunnerBridge*) {} - -template<> -void RunnableMethodTraits<AsyncRequestRunner>::RetainCallee( - AsyncRequestRunner*) {} -template<> -void RunnableMethodTraits<AsyncRequestRunner>::ReleaseCallee( - AsyncRequestRunner*) {} - - // Issue three sequential requests -- each should succeed. TEST(ResolveProxyMsgHelperTest, Sequential) { - RunnerBridge runner; + net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver; + net::ProxyService service(new MockProxyConfigService, resolver); + + MyDelegate delegate; + ResolveProxyMsgHelper helper(&delegate, &service); GURL url1("http://www.google1.com/"); GURL url2("http://www.google2.com/"); @@ -258,33 +70,56 @@ TEST(ResolveProxyMsgHelperTest, Sequential) { // Execute each request sequentially (so there are never 2 requests // outstanding at the same time). - scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get())); - result1->WaitUntilDone(); + helper.Start(url1, msg1.get()); + + // Finish ProxyService's initialization. + resolver->pending_set_pac_script_request()->CompleteNow(net::OK); - scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get())); - result2->WaitUntilDone(); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url1, resolver->pending_requests()[0]->url()); + resolver->pending_requests()[0]->results()->UseNamedProxy("result1:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); - scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get())); - result3->WaitUntilDone(); + // Check result. + EXPECT_EQ(msg1.get(), delegate.pending_result()->msg); + EXPECT_EQ(net::OK, delegate.pending_result()->error_code); + EXPECT_EQ("PROXY result1:80", delegate.pending_result()->proxy_list); + delegate.clear_pending_result(); - // Check that each request gave the expected result. + helper.Start(url2, msg2.get()); - EXPECT_EQ(msg1.get(), result1->reply_msg); - EXPECT_EQ(net::OK, result1->error_code); - EXPECT_EQ("PROXY www.google1.com:80", result1->proxy_list); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url2, resolver->pending_requests()[0]->url()); + resolver->pending_requests()[0]->results()->UseNamedProxy("result2:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); - EXPECT_EQ(msg2.get(), result2->reply_msg); - EXPECT_EQ(net::OK, result2->error_code); - EXPECT_EQ("PROXY www.google2.com:80", result2->proxy_list); + // Check result. + EXPECT_EQ(msg2.get(), delegate.pending_result()->msg); + EXPECT_EQ(net::OK, delegate.pending_result()->error_code); + EXPECT_EQ("PROXY result2:80", delegate.pending_result()->proxy_list); + delegate.clear_pending_result(); - EXPECT_EQ(msg3.get(), result3->reply_msg); - EXPECT_EQ(net::OK, result3->error_code); - EXPECT_EQ("PROXY www.google3.com:80", result3->proxy_list); + helper.Start(url3, msg3.get()); + + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url3, resolver->pending_requests()[0]->url()); + resolver->pending_requests()[0]->results()->UseNamedProxy("result3:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + // Check result. + EXPECT_EQ(msg3.get(), delegate.pending_result()->msg); + EXPECT_EQ(net::OK, delegate.pending_result()->error_code); + EXPECT_EQ("PROXY result3:80", delegate.pending_result()->proxy_list); + delegate.clear_pending_result(); } // Issue a request while one is already in progress -- should be queued. TEST(ResolveProxyMsgHelperTest, QueueRequests) { - RunnerBridge runner; + net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver; + net::ProxyService service(new MockProxyConfigService, resolver); + + MyDelegate delegate; + ResolveProxyMsgHelper helper(&delegate, &service); GURL url1("http://www.google1.com/"); GURL url2("http://www.google2.com/"); @@ -294,44 +129,64 @@ TEST(ResolveProxyMsgHelperTest, QueueRequests) { scoped_ptr<IPC::Message> msg2(new IPC::Message()); scoped_ptr<IPC::Message> msg3(new IPC::Message()); - // Make the proxy resolver hang on the next request. - runner.proxy_resolver()->x->Block(); + // Start three requests. Since the proxy resolver is async, all the + // requests will be pending. + + helper.Start(url1, msg1.get()); + + // Finish ProxyService's initialization. + resolver->pending_set_pac_script_request()->CompleteNow(net::OK); - // Start three requests. Since the proxy resolver is hung, the second two - // will be pending. + helper.Start(url2, msg2.get()); + helper.Start(url3, msg3.get()); - scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get())); - scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get())); - scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get())); + // ResolveProxyHelper only keeps 1 request outstanding in ProxyService + // at a time. + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url1, resolver->pending_requests()[0]->url()); - // Wait for the final request to have been scheduled. Otherwise we may rush - // to calling Unblock() without actually having blocked anything. - result3->WaitUntilStarted(); + resolver->pending_requests()[0]->results()->UseNamedProxy("result1:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); - // Unblock the proxy service so requests 1-3 can complete. - runner.proxy_resolver()->x->Unblock(); + // Check result. + EXPECT_EQ(msg1.get(), delegate.pending_result()->msg); + EXPECT_EQ(net::OK, delegate.pending_result()->error_code); + EXPECT_EQ("PROXY result1:80", delegate.pending_result()->proxy_list); + delegate.clear_pending_result(); - // Wait for all the requests to finish (they run in FIFO order). - result3->WaitUntilDone(); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url2, resolver->pending_requests()[0]->url()); - // Check that each call invoked the callback with the right parameters. + resolver->pending_requests()[0]->results()->UseNamedProxy("result2:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); - EXPECT_EQ(msg1.get(), result1->reply_msg); - EXPECT_EQ(net::OK, result1->error_code); - EXPECT_EQ("PROXY www.google1.com:80", result1->proxy_list); + // Check result. + EXPECT_EQ(msg2.get(), delegate.pending_result()->msg); + EXPECT_EQ(net::OK, delegate.pending_result()->error_code); + EXPECT_EQ("PROXY result2:80", delegate.pending_result()->proxy_list); + delegate.clear_pending_result(); - EXPECT_EQ(msg2.get(), result2->reply_msg); - EXPECT_EQ(net::OK, result2->error_code); - EXPECT_EQ("PROXY www.google2.com:80", result2->proxy_list); + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url3, resolver->pending_requests()[0]->url()); - EXPECT_EQ(msg3.get(), result3->reply_msg); - EXPECT_EQ(net::OK, result3->error_code); - EXPECT_EQ("PROXY www.google3.com:80", result3->proxy_list); + resolver->pending_requests()[0]->results()->UseNamedProxy("result3:80"); + resolver->pending_requests()[0]->CompleteNow(net::OK); + + // Check result. + EXPECT_EQ(msg3.get(), delegate.pending_result()->msg); + EXPECT_EQ(net::OK, delegate.pending_result()->error_code); + EXPECT_EQ("PROXY result3:80", delegate.pending_result()->proxy_list); + delegate.clear_pending_result(); } // Delete the helper while a request is in progress, and others are pending. TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) { - RunnerBridge runner; + net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver; + net::ProxyService service(new MockProxyConfigService, resolver); + + MyDelegate delegate; + scoped_ptr<ResolveProxyMsgHelper> helper( + new ResolveProxyMsgHelper(&delegate, &service)); GURL url1("http://www.google1.com/"); GURL url2("http://www.google2.com/"); @@ -343,35 +198,32 @@ TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) { IPC::Message* msg2 = new IPC::Message(); IPC::Message* msg3 = new IPC::Message(); - // Make the next request block. - runner.proxy_resolver()->x->Block(); + // Start three requests. Since the proxy resolver is async, all the + // requests will be pending. - // Start three requests; since the first one blocked, the other two should - // be pending. + helper->Start(url1, msg1); - scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1)); - scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2)); - scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3)); + // Finish ProxyService's initialization. + resolver->pending_set_pac_script_request()->CompleteNow(net::OK); - result3->WaitUntilStarted(); + helper->Start(url2, msg2); + helper->Start(url3, msg3); + + // ResolveProxyHelper only keeps 1 request outstanding in ProxyService + // at a time. + ASSERT_EQ(1u, resolver->pending_requests().size()); + EXPECT_EQ(url1, resolver->pending_requests()[0]->url()); // Delete the underlying ResolveProxyMsgHelper -- this should cancel all // the requests which are outstanding. - runner.DestroyAsyncRunner(); + helper.reset(); + + // The pending requests sent to the proxy resolver should have been cancelled. - // Unblocking the proxy resolver means the three requests can complete -- - // however they should not try to notify the delegate since we have already - // deleted the helper. - runner.proxy_resolver()->x->Unblock(); + EXPECT_EQ(0u, resolver->pending_requests().size()); - // Check that none of the requests were sent to the delegate. - EXPECT_FALSE( - result1->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2))); - EXPECT_FALSE( - result2->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2))); - EXPECT_FALSE( - result3->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2))); + EXPECT_EQ(NULL, delegate.pending_result()); // It should also be the case that msg1, msg2, msg3 were deleted by the - // cancellation. (Else will show up as a leak in Purify). + // cancellation. (Else will show up as a leak in Purify/Valgrind). } diff --git a/net/net.gyp b/net/net.gyp index 3bba793..cc993c7 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -498,6 +498,7 @@ 'http/http_util_unittest.cc', 'http/http_vary_data_unittest.cc', 'proxy/init_proxy_resolver_unittest.cc', + 'proxy/mock_proxy_resolver.h', 'proxy/proxy_config_service_linux_unittest.cc', 'proxy/proxy_config_service_win_unittest.cc', 'proxy/proxy_config_unittest.cc', diff --git a/net/proxy/mock_proxy_resolver.h b/net/proxy/mock_proxy_resolver.h index 0dac40b..0b1e8a5 100644 --- a/net/proxy/mock_proxy_resolver.h +++ b/net/proxy/mock_proxy_resolver.h @@ -1,40 +1,18 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. +#ifndef NET_PROXY_MOCK_PROXY_RESOLVER_H_ +#define NET_PROXY_MOCK_PROXY_RESOLVER_H_ + #include <vector> #include "base/logging.h" -#include "base/string_util.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 "testing/gtest/include/gtest/gtest.h" -// TODO(eroman): Write a test which exercises -// ProxyService::SuspendAllPendingRequests(). namespace net { -namespace { - -class MockProxyConfigService: public ProxyConfigService { - public: - MockProxyConfigService() {} // Direct connect. - explicit MockProxyConfigService(const ProxyConfig& pc) : config(pc) {} - explicit MockProxyConfigService(const std::string& pac_url) { - config.pac_url = GURL(pac_url); - } - - virtual int GetProxyConfig(ProxyConfig* results) { - *results = config; - return OK; - } - - ProxyConfig config; -}; // Asynchronous mock proxy resolver. All requests complete asynchronously, // user must call Request::CompleteNow() on a pending request to signal it. @@ -133,7 +111,7 @@ class MockAsyncProxyResolverBase : public ProxyResolver { virtual int SetPacScript(const GURL& pac_url, const std::string& pac_bytes, CompletionCallback* callback) { - EXPECT_EQ(NULL, pending_set_pac_script_request_.get()); + DCHECK(!pending_set_pac_script_request_.get()); pending_set_pac_script_request_.reset( new SetPacScriptRequest(this, pac_url, pac_bytes, callback)); // Finished when user calls SetPacScriptRequest::CompleteNow(). @@ -160,7 +138,7 @@ class MockAsyncProxyResolverBase : public ProxyResolver { } void RemovePendingSetPacScriptRequest(SetPacScriptRequest* request) { - EXPECT_EQ(request, pending_set_pac_script_request()); + DCHECK_EQ(request, pending_set_pac_script_request()); pending_set_pac_script_request_.reset(); } @@ -186,1343 +164,6 @@ class MockAsyncProxyResolverExpectsBytes : public MockAsyncProxyResolverBase { : 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 ProxyScriptFetcher { - public: - MockProxyScriptFetcher() - : pending_request_callback_(NULL), pending_request_bytes_(NULL) { - } - - // ProxyScriptFetcher implementation. - virtual int Fetch(const GURL& url, - std::string* bytes, - CompletionCallback* callback) { - DCHECK(!has_pending_request()); - - // Save the caller's information, and have them wait. - pending_request_url_ = url; - pending_request_callback_ = callback; - pending_request_bytes_ = bytes; - return ERR_IO_PENDING; - } - - void NotifyFetchCompletion(int result, const std::string& bytes) { - DCHECK(has_pending_request()); - *pending_request_bytes_ = bytes; - CompletionCallback* callback = pending_request_callback_; - pending_request_callback_ = NULL; - callback->Run(result); - } - - virtual void Cancel() {} - - const GURL& pending_request_url() const { - return pending_request_url_; - } - - bool has_pending_request() const { - return pending_request_callback_ != NULL; - } - - private: - GURL pending_request_url_; - CompletionCallback* pending_request_callback_; - std::string* pending_request_bytes_; -}; - -TEST(ProxyServiceTest, Direct) { - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - ProxyService service(new MockProxyConfigService, resolver); - - GURL url("http://www.google.com/"); - - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(resolver->pending_requests().empty()); - - EXPECT_TRUE(info.is_direct()); -} - -TEST(ProxyServiceTest, PAC) { - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - GURL url("http://www.google.com/"); - - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(url, &info, &callback, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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(OK); - - EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); -} - -// Test that the proxy resolver does not see the URL's username/password -// or its reference section. -TEST(ProxyServiceTest, PAC_NoIdentityOrHash) { - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - GURL url("http://username:password@www.google.com/?ref#hash#hash"); - - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(url, &info, &callback, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - ASSERT_EQ(1u, resolver->pending_requests().size()); - // The URL should have been simplified, stripping the username/password/hash. - EXPECT_EQ(GURL("http://www.google.com/?ref"), - resolver->pending_requests()[0]->url()); - - // We end here without ever completing the request -- destruction of - // ProxyService will cancel the outstanding request. -} - -TEST(ProxyServiceTest, PAC_FailoverToDirect) { - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - GURL url("http://www.google.com/"); - - ProxyInfo info; - TestCompletionCallback callback1; - int rv = service.ResolveProxy(url, &info, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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(OK); - - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); - - // Now, imagine that connecting to foopy:8080 fails. - TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); -} - -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.) - // TODO(eroman): change this comment. - - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - // Start first resolve request. - GURL url("http://www.google.com/"); - ProxyInfo info; - TestCompletionCallback callback1; - int rv = service.ResolveProxy(url, &info, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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(ERR_FAILED); - - EXPECT_EQ(ERR_FAILED, callback1.WaitForResult()); - - // The second resolve request will automatically select direct connect, - // because it has cached the configuration as being bad. - TestCompletionCallback callback2; - rv = service.ResolveProxy(url, &info, &callback2, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - 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. - TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); - EXPECT_EQ(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(OK); - - EXPECT_EQ(OK, callback3.WaitForResult()); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); -} - -TEST(ProxyServiceTest, ProxyFallback) { - // Test what happens when we specify multiple proxy servers and some of them - // are bad. - - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - GURL url("http://www.google.com/"); - - // Get the proxy information. - ProxyInfo info; - TestCompletionCallback callback1; - int rv = service.ResolveProxy(url, &info, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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(OK); - - // The first item is valid. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); - - // Fake an error on the proxy. - TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); - EXPECT_EQ(OK, rv); - - // The second proxy should be specified. - EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); - - TestCompletionCallback callback3; - rv = service.ResolveProxy(url, &info, &callback3, NULL); - EXPECT_EQ(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 -- 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(OK); - - EXPECT_EQ(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. - TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); - EXPECT_EQ(OK, rv); - EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); - - // Fake another error, the last proxy is gone, the list should now be empty. - TestCompletionCallback callback5; - rv = service.ReconsiderProxyAfterError(url, &info, &callback5, NULL); - EXPECT_EQ(OK, rv); // We try direct. - EXPECT_TRUE(info.is_direct()); - - // If it fails again, we don't have anything else to try. - TestCompletionCallback callback6; - rv = service.ReconsiderProxyAfterError(url, &info, &callback6, NULL); - EXPECT_EQ(ERR_FAILED, rv); - - // TODO(nsylvain): Test that the proxy can be retried after the delay. -} - -TEST(ProxyServiceTest, ProxyFallback_NewSettings) { - // Test proxy failover when new settings are available. - - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - GURL url("http://www.google.com/"); - - // Get the proxy information. - ProxyInfo info; - TestCompletionCallback callback1; - int rv = service.ResolveProxy(url, &info, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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(OK); - - // The first item is valid. - EXPECT_EQ(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 = ProxyConfig(); - config_service->config.pac_url = GURL("http://foopy-new/proxy.pac"); - - TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy-new/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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(OK); - - // The first proxy is still there since the configuration changed. - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); - - // We fake another error. It should now ignore the first one. - TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); - EXPECT_EQ(OK, rv); - EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); - - // We simulate a new configuration. - config_service->config = ProxyConfig(); - config_service->config.pac_url = GURL("http://foopy-new2/proxy.pac"); - - // We fake another error. It should go back to the first proxy. - TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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(OK); - - EXPECT_EQ(OK, callback4.WaitForResult()); - EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); -} - -TEST(ProxyServiceTest, ProxyFallback_BadConfig) { - // Test proxy failover when the configuration is bad. - - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - GURL url("http://www.google.com/"); - - // Get the proxy information. - ProxyInfo info; - TestCompletionCallback callback1; - int rv = service.ResolveProxy(url, &info, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - 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(OK); - - // The first item is valid. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); - - // Fake a proxy error. - TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); - EXPECT_EQ(OK, rv); - - // The first proxy is ignored, and the second one is selected. - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); - - // Fake a PAC failure. - ProxyInfo info2; - TestCompletionCallback callback3; - rv = service.ResolveProxy(url, &info2, &callback3, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - ASSERT_EQ(1u, resolver->pending_requests().size()); - EXPECT_EQ(url, resolver->pending_requests()[0]->url()); - - resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); - - // No proxy servers are returned. It's a direct connection. - EXPECT_EQ(ERR_FAILED, callback3.WaitForResult()); - EXPECT_TRUE(info2.is_direct()); - - // The PAC will now be fixed and will return a proxy server. - // It should also clear the list of bad proxies. - - // Try to resolve, it will still return "direct" because we have no reason - // to check the config since everything works. - ProxyInfo info3; - TestCompletionCallback callback4; - rv = service.ResolveProxy(url, &info3, &callback4, NULL); - EXPECT_EQ(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. - TestCompletionCallback callback5; - rv = service.ReconsiderProxyAfterError(url, &info3, &callback5, NULL); - EXPECT_EQ(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(OK); - - // The first proxy is still there since the list of bad proxies got cleared. - EXPECT_EQ(OK, callback5.WaitForResult()); - EXPECT_FALSE(info3.is_direct()); - EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); -} - -TEST(ProxyServiceTest, ProxyBypassList) { - // Test what happens when a proxy bypass list is specified. - - ProxyInfo info; - ProxyConfig config; - config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); - config.auto_detect = false; - config.proxy_bypass_local_names = true; - - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver()); - GURL url("http://www.google.com/"); - // Get the proxy information. - TestCompletionCallback callback; - int rv = service.ResolveProxy(url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - } - - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver()); - GURL test_url("http://local"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.org"); - config.proxy_bypass_local_names = true; - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.webkit.org"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.org"); - config.proxy_bypass.push_back("7*"); - config.proxy_bypass_local_names = true; - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://74.125.19.147"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.org"); - config.proxy_bypass_local_names = true; - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.msn.com"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - } - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.MSN.COM"); - config.proxy_bypass_local_names = true; - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.msnbc.msn.com"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.msn.com"); - config.proxy_bypass_local_names = true; - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("HTTP://WWW.MSNBC.MSN.COM"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } -} - -TEST(ProxyServiceTest, ProxyBypassListWithPorts) { - // Test port specification in bypass list entries. - ProxyInfo info; - ProxyConfig config; - config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); - config.auto_detect = false; - config.proxy_bypass_local_names = false; - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.example.com:99"); - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - { - GURL test_url("http://www.example.com:99"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - { - GURL test_url("http://www.example.com:100"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - } - { - GURL test_url("http://www.example.com"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - } - } - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.example.com:80"); - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.example.com"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("*.example.com"); - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.example.com:99"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - - // IPv6 with port. - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99"); - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - { - GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - { - GURL test_url("http://[3ffe:2a00:100:7031::1]/"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - } - } - - // IPv6 without port. The bypass entry ought to work without the - // brackets, but the bypass matching logic in ProxyService is - // currently limited. - config.proxy_bypass.clear(); - config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]"); - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - { - GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - { - GURL test_url("http://[3ffe:2a00:100:7031::1]/"); - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - } - } -} - -TEST(ProxyServiceTest, PerProtocolProxyTests) { - ProxyConfig config; - config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080"); - config.auto_detect = false; - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.msn.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); - } - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("ftp://ftp.google.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_TRUE(info.is_direct()); - EXPECT_EQ("direct://", info.proxy_server().ToURI()); - } - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("https://webbranch.techcu.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); - } - { - config.proxy_rules.ParseFromString("foopy1:8080"); - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.microsoft.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(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 -// fall back to the SOCKS proxy. -TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { - ProxyConfig config; - config.proxy_rules.ParseFromString("http=foopy1:8080;socks=foopy2:1080"); - config.auto_detect = false; - EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, - config.proxy_rules.type); - - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("http://www.msn.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); - } - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("ftp://ftp.google.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); - } - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("https://webbranch.techcu.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); - } - { - ProxyService service(new MockProxyConfigService(config), - new MockAsyncProxyResolver); - GURL test_url("unknown://www.microsoft.com"); - ProxyInfo info; - TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, &info, &callback, NULL); - EXPECT_EQ(OK, rv); - EXPECT_FALSE(info.is_direct()); - EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); - } -} - -// Test cancellation of an in-progress request. -TEST(ProxyServiceTest, CancelInProgressRequest) { - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; - - ProxyService service(config_service, resolver); - - // Start 3 requests. - - ProxyInfo info1; - TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), &info1, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // Nothing has been sent to the proxy resolver yet, since the proxy - // resolver has not been configured yet. - ASSERT_EQ(0u, resolver->pending_requests().size()); - - // Successfully initialize the PAC script. - EXPECT_EQ(GURL("http://foopy/proxy.pac"), - resolver->pending_set_pac_script_request()->pac_url()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - ASSERT_EQ(1u, resolver->pending_requests().size()); - EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); - - ProxyInfo info2; - TestCompletionCallback callback2; - ProxyService::PacRequest* request2; - rv = service.ResolveProxy( - GURL("http://request2"), &info2, &callback2, &request2); - EXPECT_EQ(ERR_IO_PENDING, rv); - ASSERT_EQ(2u, resolver->pending_requests().size()); - EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); - - ProxyInfo info3; - TestCompletionCallback callback3; - rv = service.ResolveProxy( - GURL("http://request3"), &info3, &callback3, NULL); - EXPECT_EQ(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 - service.CancelPacRequest(request2); - - 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()); - - // 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(OK); - - resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - // Complete and verify that requests ran as expected. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); - - EXPECT_FALSE(callback2.have_result()); // Cancelled. - ASSERT_EQ(1u, resolver->cancelled_requests().size()); - EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url()); - - EXPECT_EQ(OK, callback3.WaitForResult()); - EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); -} - -// Test the initial PAC download for ProxyResolverWithoutFetch. -TEST(ProxyServiceTest, InitialPACScriptDownload) { - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolverExpectsBytes* resolver = - new MockAsyncProxyResolverExpectsBytes; - - ProxyService service(config_service, resolver); - - MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; - service.SetProxyScriptFetcher(fetcher); - - // Start 3 requests. - - ProxyInfo info1; - TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), &info1, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // 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()); - - ProxyInfo info2; - TestCompletionCallback callback2; - rv = service.ResolveProxy( - GURL("http://request2"), &info2, &callback2, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - ProxyInfo info3; - TestCompletionCallback callback3; - rv = service.ResolveProxy( - GURL("http://request3"), &info3, &callback3, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // Nothing has been sent to the resolver yet. - EXPECT_TRUE(resolver->pending_requests().empty()); - - // 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(OK, "pac-v1"); - - // Now that the PAC script is downloaded, it will have been sent to the proxy - // resolver. - EXPECT_EQ("pac-v1", resolver->pending_set_pac_script_request()->pac_bytes()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - 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()); - - // Complete all the requests (in some order). - // Note that as we complete requests, they shift up in |pending_requests()|. - - resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80"); - resolver->pending_requests()[2]->CompleteNow(OK); - - resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - // Complete and verify that requests ran as expected. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); - - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); - - EXPECT_EQ(OK, callback3.WaitForResult()); - EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); -} - -// Test cancellation of a request, while the PAC script is being fetched. -TEST(ProxyServiceTest, CancelWhilePACFetching) { - MockProxyConfigService* config_service = - new MockProxyConfigService("http://foopy/proxy.pac"); - - MockAsyncProxyResolverExpectsBytes* resolver = - new MockAsyncProxyResolverExpectsBytes; - - ProxyService service(config_service, resolver); - - MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; - service.SetProxyScriptFetcher(fetcher); - - // Start 3 requests. - ProxyInfo info1; - TestCompletionCallback callback1; - ProxyService::PacRequest* request1; - int rv = service.ResolveProxy( - GURL("http://request1"), &info1, &callback1, &request1); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // 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()); - - ProxyInfo info2; - TestCompletionCallback callback2; - ProxyService::PacRequest* request2; - rv = service.ResolveProxy( - GURL("http://request2"), &info2, &callback2, &request2); - EXPECT_EQ(ERR_IO_PENDING, rv); - - ProxyInfo info3; - TestCompletionCallback callback3; - rv = service.ResolveProxy( - GURL("http://request3"), &info3, &callback3, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // Nothing has been sent to the resolver yet. - EXPECT_TRUE(resolver->pending_requests().empty()); - - // Cancel the first 2 requests. - 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(OK, "pac-v1"); - - // Now that the PAC script is downloaded, it will have been sent to the - // proxy resolver. - EXPECT_EQ("pac-v1", resolver->pending_set_pac_script_request()->pac_bytes()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - ASSERT_EQ(1u, resolver->pending_requests().size()); - EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url()); - - // Complete all the requests. - resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - EXPECT_EQ(OK, callback3.WaitForResult()); - EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); - - EXPECT_TRUE(resolver->cancelled_requests().empty()); - - EXPECT_FALSE(callback1.have_result()); // Cancelled. - EXPECT_FALSE(callback2.have_result()); // Cancelled. -} - -// Test that if auto-detect fails, we fall-back to the custom pac. -TEST(ProxyServiceTest, FallbackFromAutodetectToCustomPac) { - ProxyConfig config; - config.auto_detect = true; - config.pac_url = GURL("http://foopy/proxy.pac"); - config.proxy_rules.ParseFromString("http=foopy:80"); // Won't be used. - - MockProxyConfigService* config_service = new MockProxyConfigService(config); - MockAsyncProxyResolverExpectsBytes* resolver = - new MockAsyncProxyResolverExpectsBytes; - ProxyService service(config_service, resolver); - - MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; - service.SetProxyScriptFetcher(fetcher); - - // Start 2 requests. - - ProxyInfo info1; - TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), &info1, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - ProxyInfo info2; - TestCompletionCallback callback2; - ProxyService::PacRequest* request2; - rv = service.ResolveProxy( - GURL("http://request2"), &info2, &callback2, &request2); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // Check that nothing has been sent to the proxy resolver yet. - ASSERT_EQ(0u, resolver->pending_requests().size()); - - // It should be trying to auto-detect first -- FAIL the autodetect during - // the script download. - EXPECT_TRUE(fetcher->has_pending_request()); - EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); - fetcher->NotifyFetchCompletion(ERR_FAILED, ""); - - // Next it should be trying the custom PAC url. - EXPECT_TRUE(fetcher->has_pending_request()); - EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); - fetcher->NotifyFetchCompletion(OK, "custom-pac-script"); - - EXPECT_EQ("custom-pac-script", - resolver->pending_set_pac_script_request()->pac_bytes()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - // Now finally, the pending requests should have been sent to the resolver - // (which was initialized with custom PAC script). - - ASSERT_EQ(2u, resolver->pending_requests().size()); - EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); - EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); - - // Complete the pending requests. - resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80"); - resolver->pending_requests()[1]->CompleteNow(OK); - resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - // Verify that requests ran as expected. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); - - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); -} - -// This is the same test as FallbackFromAutodetectToCustomPac, except -// the auto-detect script fails parsing rather than downloading. -TEST(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) { - ProxyConfig config; - config.auto_detect = true; - config.pac_url = GURL("http://foopy/proxy.pac"); - config.proxy_rules.ParseFromString("http=foopy:80"); // Won't be used. - - MockProxyConfigService* config_service = new MockProxyConfigService(config); - MockAsyncProxyResolverExpectsBytes* resolver = - new MockAsyncProxyResolverExpectsBytes; - ProxyService service(config_service, resolver); - - MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; - service.SetProxyScriptFetcher(fetcher); - - // Start 2 requests. - - ProxyInfo info1; - TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), &info1, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - ProxyInfo info2; - TestCompletionCallback callback2; - ProxyService::PacRequest* request2; - rv = service.ResolveProxy( - GURL("http://request2"), &info2, &callback2, &request2); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // Check that nothing has been sent to the proxy resolver yet. - ASSERT_EQ(0u, resolver->pending_requests().size()); - - // It should be trying to auto-detect first -- succeed the download. - EXPECT_TRUE(fetcher->has_pending_request()); - EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); - fetcher->NotifyFetchCompletion(OK, "invalid-script-contents"); - - // Simulate a parse error. - EXPECT_EQ("invalid-script-contents", - resolver->pending_set_pac_script_request()->pac_bytes()); - resolver->pending_set_pac_script_request()->CompleteNow( - ERR_PAC_SCRIPT_FAILED); - - // Next it should be trying the custom PAC url. - EXPECT_TRUE(fetcher->has_pending_request()); - EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); - fetcher->NotifyFetchCompletion(OK, "custom-pac-script"); - - EXPECT_EQ("custom-pac-script", - resolver->pending_set_pac_script_request()->pac_bytes()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - // Now finally, the pending requests should have been sent to the resolver - // (which was initialized with custom PAC script). - - ASSERT_EQ(2u, resolver->pending_requests().size()); - EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); - EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); - - // Complete the pending requests. - resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80"); - resolver->pending_requests()[1]->CompleteNow(OK); - resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - // Verify that requests ran as expected. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); - - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); -} - -// Test that if all of auto-detect, a custom PAC script, and manual settings -// are given, then we will try them in that order. -TEST(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) { - ProxyConfig config; - config.auto_detect = true; - config.pac_url = GURL("http://foopy/proxy.pac"); - config.proxy_rules.ParseFromString("http=foopy:80"); - - MockProxyConfigService* config_service = new MockProxyConfigService(config); - MockAsyncProxyResolverExpectsBytes* resolver = - new MockAsyncProxyResolverExpectsBytes; - ProxyService service(config_service, resolver); - - MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; - service.SetProxyScriptFetcher(fetcher); - - // Start 2 requests. - - ProxyInfo info1; - TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), &info1, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - ProxyInfo info2; - TestCompletionCallback callback2; - ProxyService::PacRequest* request2; - rv = service.ResolveProxy( - GURL("http://request2"), &info2, &callback2, &request2); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // Check that nothing has been sent to the proxy resolver yet. - ASSERT_EQ(0u, resolver->pending_requests().size()); - - // It should be trying to auto-detect first -- fail the download. - EXPECT_TRUE(fetcher->has_pending_request()); - EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); - fetcher->NotifyFetchCompletion(ERR_FAILED, ""); - - // Next it should be trying the custom PAC url -- fail the download. - EXPECT_TRUE(fetcher->has_pending_request()); - EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); - fetcher->NotifyFetchCompletion(ERR_FAILED, ""); - - // Since we never managed to initialize a ProxyResolver, nothing should have - // been sent to it. - ASSERT_EQ(0u, resolver->pending_requests().size()); - - // Verify that requests ran as expected -- they should have fallen back to - // the manual proxy configuration for HTTP urls. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_EQ("foopy:80", info1.proxy_server().ToURI()); - - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_EQ("foopy:80", info2.proxy_server().ToURI()); -} - -// Test that the bypass rules are NOT applied when using autodetect. -TEST(ProxyServiceTest, BypassDoesntApplyToPac) { - ProxyConfig config; - config.auto_detect = true; - config.pac_url = GURL("http://foopy/proxy.pac"); - config.proxy_rules.ParseFromString("http=foopy:80"); // Not used. - config.proxy_bypass.push_back("www.google.com"); - - MockProxyConfigService* config_service = new MockProxyConfigService(config); - MockAsyncProxyResolverExpectsBytes* resolver = - new MockAsyncProxyResolverExpectsBytes; - ProxyService service(config_service, resolver); - - MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; - service.SetProxyScriptFetcher(fetcher); - - // Start 1 requests. - - ProxyInfo info1; - TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://www.google.com"), &info1, &callback1, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - // Check that nothing has been sent to the proxy resolver yet. - ASSERT_EQ(0u, resolver->pending_requests().size()); - - // It should be trying to auto-detect first -- succeed the download. - EXPECT_TRUE(fetcher->has_pending_request()); - EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); - fetcher->NotifyFetchCompletion(OK, "auto-detect"); - - EXPECT_EQ("auto-detect", - resolver->pending_set_pac_script_request()->pac_bytes()); - resolver->pending_set_pac_script_request()->CompleteNow(OK); - - ASSERT_EQ(1u, resolver->pending_requests().size()); - EXPECT_EQ(GURL("http://www.google.com"), - resolver->pending_requests()[0]->url()); - - // Complete the pending request. - resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - // Verify that request ran as expected. - EXPECT_EQ(OK, callback1.WaitForResult()); - EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); - - // Start another request, it should pickup the bypass item. - ProxyInfo info2; - TestCompletionCallback callback2; - rv = service.ResolveProxy( - GURL("http://www.google.com"), &info2, &callback2, NULL); - EXPECT_EQ(ERR_IO_PENDING, rv); - - ASSERT_EQ(1u, resolver->pending_requests().size()); - EXPECT_EQ(GURL("http://www.google.com"), - resolver->pending_requests()[0]->url()); - - // Complete the pending request. - resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); - resolver->pending_requests()[0]->CompleteNow(OK); - - EXPECT_EQ(OK, callback2.WaitForResult()); - EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); -} - -TEST(ProxyServiceTest, ResetProxyConfigService) { - ProxyConfig config1; - config1.proxy_rules.ParseFromString("foopy1:8080"); - config1.auto_detect = false; - ProxyService service(new MockProxyConfigService(config1), - new MockAsyncProxyResolverExpectsBytes); - - ProxyInfo info; - TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), &info, &callback1, NULL); - EXPECT_EQ(OK, rv); - EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); - - ProxyConfig config2; - config2.proxy_rules.ParseFromString("foopy2:8080"); - config2.auto_detect = false; - service.ResetConfigService(new MockProxyConfigService(config2)); - TestCompletionCallback callback2; - rv = service.ResolveProxy(GURL("http://request2"), &info, &callback2, NULL); - EXPECT_EQ(OK, rv); - EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); -} - -TEST(ProxyServiceTest, IsLocalName) { - const struct { - const char* url; - bool expected_is_local; - } tests[] = { - // Single-component hostnames are considered local. - {"http://localhost/x", true}, - {"http://www", true}, - - // IPv4 loopback interface. - {"http://127.0.0.1/x", true}, - {"http://127.0.0.1:80/x", true}, - - // IPv6 loopback interface. - {"http://[::1]:80/x", true}, - {"http://[0:0::1]:6233/x", true}, - {"http://[0:0:0:0:0:0:0:1]/x", true}, - - // Non-local URLs. - {"http://foo.com/", false}, - {"http://localhost.i/", false}, - {"http://www.google.com/", false}, - {"http://192.168.0.1/", false}, - - // Try with different protocols. - {"ftp://127.0.0.1/x", true}, - {"ftp://foobar.com/x", false}, - - // This is a bit of a gray-area, but GURL does not strip trailing dots - // in host-names, so the following are considered non-local. - {"http://www./x", false}, - {"http://localhost./x", false}, - }; - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - SCOPED_TRACE(StringPrintf("Test[%d]: %s", i, tests[i].url)); - bool is_local = ProxyService::IsLocalName(GURL(tests[i].url)); - EXPECT_EQ(tests[i].expected_is_local, is_local); - } -} - } // namespace net + +#endif // NET_PROXY_MOCK_PROXY_RESOLVER_H_ diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index 3b3eb49..f4deb67 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc @@ -9,6 +9,7 @@ #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" +#include "net/proxy/mock_proxy_resolver.h" #include "net/proxy/proxy_config_service.h" #include "net/proxy/proxy_resolver.h" #include "net/proxy/proxy_script_fetcher.h" @@ -36,156 +37,6 @@ class MockProxyConfigService: public ProxyConfigService { ProxyConfig config; }; -// Asynchronous mock proxy resolver. All requests complete asynchronously, -// user must call Request::CompleteNow() on a pending request to signal it. -class MockAsyncProxyResolverBase : public ProxyResolver { - public: - class Request : public base::RefCounted<Request> { - public: - Request(MockAsyncProxyResolverBase* resolver, - const GURL& url, - ProxyInfo* results, - CompletionCallback* callback) - : resolver_(resolver), - url_(url), - results_(results), - callback_(callback), - origin_loop_(MessageLoop::current()) { - } - - const GURL& url() const { return url_; } - ProxyInfo* results() const { return results_; } - CompletionCallback* callback() const { return callback_; } - - void CompleteNow(int rv) { - CompletionCallback* callback = callback_; - - // May delete |this|. - resolver_->RemovePendingRequest(this); - - callback->Run(rv); - } - - private: - MockAsyncProxyResolverBase* resolver_; - const GURL url_; - ProxyInfo* results_; - CompletionCallback* callback_; - MessageLoop* origin_loop_; - }; - - class SetPacScriptRequest { - public: - SetPacScriptRequest(MockAsyncProxyResolverBase* resolver, - const GURL& pac_url, - const std::string& pac_bytes, - CompletionCallback* callback) - : resolver_(resolver), - pac_url_(pac_url), - pac_bytes_(pac_bytes), - callback_(callback), - origin_loop_(MessageLoop::current()) { - } - - const GURL& pac_url() const { return pac_url_; } - const std::string& pac_bytes() const { return pac_bytes_; } - - void CompleteNow(int rv) { - CompletionCallback* callback = callback_; - - // Will delete |this|. - resolver_->RemovePendingSetPacScriptRequest(this); - - callback->Run(rv); - } - - private: - MockAsyncProxyResolverBase* resolver_; - const GURL pac_url_; - const std::string pac_bytes_; - CompletionCallback* callback_; - MessageLoop* origin_loop_; - }; - - typedef std::vector<scoped_refptr<Request> > RequestsList; - - // ProxyResolver implementation: - virtual int GetProxyForURL(const GURL& url, - ProxyInfo* results, - CompletionCallback* callback, - RequestHandle* request_handle) { - scoped_refptr<Request> request = new Request(this, url, results, callback); - pending_requests_.push_back(request); - - if (request_handle) - *request_handle = reinterpret_cast<RequestHandle>(request.get()); - - // Test code completes the request by calling request->CompleteNow(). - return ERR_IO_PENDING; - } - - virtual void CancelRequest(RequestHandle request_handle) { - scoped_refptr<Request> request = reinterpret_cast<Request*>(request_handle); - cancelled_requests_.push_back(request); - RemovePendingRequest(request); - } - - virtual int SetPacScript(const GURL& pac_url, - const std::string& pac_bytes, - CompletionCallback* callback) { - EXPECT_EQ(NULL, pending_set_pac_script_request_.get()); - pending_set_pac_script_request_.reset( - new SetPacScriptRequest(this, pac_url, pac_bytes, callback)); - // Finished when user calls SetPacScriptRequest::CompleteNow(). - return ERR_IO_PENDING; - } - - const RequestsList& pending_requests() const { - return pending_requests_; - } - - const RequestsList& cancelled_requests() const { - return cancelled_requests_; - } - - SetPacScriptRequest* pending_set_pac_script_request() const { - return pending_set_pac_script_request_.get(); - } - - 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); - } - - void RemovePendingSetPacScriptRequest(SetPacScriptRequest* request) { - EXPECT_EQ(request, pending_set_pac_script_request()); - pending_set_pac_script_request_.reset(); - } - - protected: - explicit MockAsyncProxyResolverBase(bool expects_pac_bytes) - : ProxyResolver(expects_pac_bytes) {} - - private: - RequestsList pending_requests_; - RequestsList cancelled_requests_; - scoped_ptr<SetPacScriptRequest> pending_set_pac_script_request_; -}; - -class MockAsyncProxyResolver : public MockAsyncProxyResolverBase { - public: - MockAsyncProxyResolver() - : MockAsyncProxyResolverBase(false /*expects_pac_bytes*/) {} -}; - -class MockAsyncProxyResolverExpectsBytes : public MockAsyncProxyResolverBase { - public: - MockAsyncProxyResolverExpectsBytes() - : MockAsyncProxyResolverBase(true /*expects_pac_bytes*/) {} -}; - } // namespace // A mock ProxyScriptFetcher. No result will be returned to the fetch client |