summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/net/resolve_proxy_msg_helper_unittest.cc408
-rw-r--r--net/net.gyp1
-rw-r--r--net/proxy/mock_proxy_resolver.h1375
-rw-r--r--net/proxy/proxy_service_unittest.cc151
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