summaryrefslogtreecommitdiffstats
path: root/chrome/browser/net
diff options
context:
space:
mode:
authorhamaji@chromium.org <hamaji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-06 12:11:05 +0000
committerhamaji@chromium.org <hamaji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-06 12:11:05 +0000
commita692c6f3a59e711bc38fc72fce3c938deec64da0 (patch)
tree0583e80059992b55252390a7891e1651ba1c2ab3 /chrome/browser/net
parent4bd778d6cd4e108a38caeda9b283f01691fe7ecf (diff)
downloadchromium_src-a692c6f3a59e711bc38fc72fce3c938deec64da0.zip
chromium_src-a692c6f3a59e711bc38fc72fce3c938deec64da0.tar.gz
chromium_src-a692c6f3a59e711bc38fc72fce3c938deec64da0.tar.bz2
Reverting r22591. It seems to be making purify fail.
r22590: http://build.chromium.org/buildbot/waterfall/builders/XP%20Unit%20(purify)/builds/5026 r22591: http://build.chromium.org/buildbot/waterfall/builders/XP%20Unit%20(purify)/builds/5030 TEST=none BUG=none TBR=eroman Review URL: http://codereview.chromium.org/165048 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22603 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/net')
-rw-r--r--chrome/browser/net/resolve_proxy_msg_helper_unittest.cc408
1 files changed, 278 insertions, 130 deletions
diff --git a/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc b/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc
index b9974ca..ef016d3 100644
--- a/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc
+++ b/chrome/browser/net/resolve_proxy_msg_helper_unittest.cc
@@ -6,12 +6,13 @@
#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");
@@ -19,45 +20,232 @@ class MockProxyConfigService : public net::ProxyConfigService {
}
};
-class MyDelegate : public ResolveProxyMsgHelper::Delegate {
+// 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 {
public:
- 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:
+ 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();
+ }
+
virtual void OnResolveProxyCompleted(IPC::Message* reply_msg,
int error_code,
const std::string& proxy_list) {
- DCHECK(!pending_result_.get());
- pending_result_.reset(new PendingResult(reply_msg, error_code, 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();
}
- const PendingResult* pending_result() const { return pending_result_.get(); }
+ // Start an async request on the io thread.
+ ResultFuture* Start(const GURL& url, IPC::Message* reply_msg) {
+ ResultFuture* future = new ResultFuture();
- void clear_pending_result() {
- pending_result_.reset();
+ 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();
}
private:
- scoped_ptr<PendingResult> pending_result_;
+ base::Thread io_thread_;
+ base::WaitableEvent done_;
+
+ net::ProxyService* proxy_service_;
+ MockProxyResolver* proxy_resolver_; // Owned by proxy_service_.
+
+ AsyncRequestRunner* async_runner_;
};
+// 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) {
- net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver;
- net::ProxyService service(new MockProxyConfigService, resolver);
-
- MyDelegate delegate;
- ResolveProxyMsgHelper helper(&delegate, &service);
+ RunnerBridge runner;
GURL url1("http://www.google1.com/");
GURL url2("http://www.google2.com/");
@@ -70,56 +258,33 @@ TEST(ResolveProxyMsgHelperTest, Sequential) {
// Execute each request sequentially (so there are never 2 requests
// outstanding at the same time).
- helper.Start(url1, msg1.get());
-
- // Finish ProxyService's initialization.
- resolver->pending_set_pac_script_request()->CompleteNow(net::OK);
+ scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get()));
+ result1->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> result2(runner.Start(url2, msg2.get()));
+ result2->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();
+ scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get()));
+ result3->WaitUntilDone();
- helper.Start(url2, msg2.get());
+ // Check that each request gave the expected result.
- 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(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);
- 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();
+ EXPECT_EQ(msg3.get(), result3->reply_msg);
+ EXPECT_EQ(net::OK, result3->error_code);
+ EXPECT_EQ("PROXY www.google3.com:80", result3->proxy_list);
}
// Issue a request while one is already in progress -- should be queued.
TEST(ResolveProxyMsgHelperTest, QueueRequests) {
- net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver;
- net::ProxyService service(new MockProxyConfigService, resolver);
-
- MyDelegate delegate;
- ResolveProxyMsgHelper helper(&delegate, &service);
+ RunnerBridge runner;
GURL url1("http://www.google1.com/");
GURL url2("http://www.google2.com/");
@@ -129,64 +294,44 @@ TEST(ResolveProxyMsgHelperTest, QueueRequests) {
scoped_ptr<IPC::Message> msg2(new IPC::Message());
scoped_ptr<IPC::Message> msg3(new IPC::Message());
- // 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);
+ // Make the proxy resolver hang on the next request.
+ runner.proxy_resolver()->x->Block();
- helper.Start(url2, msg2.get());
- helper.Start(url3, msg3.get());
+ // Start three requests. Since the proxy resolver is hung, the second two
+ // will be pending.
- // 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());
+ 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()));
- resolver->pending_requests()[0]->results()->UseNamedProxy("result1:80");
- resolver->pending_requests()[0]->CompleteNow(net::OK);
+ // Wait for the final request to have been scheduled. Otherwise we may rush
+ // to calling Unblock() without actually having blocked anything.
+ result3->WaitUntilStarted();
- // 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();
+ // Unblock the proxy service so requests 1-3 can complete.
+ runner.proxy_resolver()->x->Unblock();
- ASSERT_EQ(1u, resolver->pending_requests().size());
- EXPECT_EQ(url2, resolver->pending_requests()[0]->url());
+ // Wait for all the requests to finish (they run in FIFO order).
+ result3->WaitUntilDone();
- resolver->pending_requests()[0]->results()->UseNamedProxy("result2:80");
- resolver->pending_requests()[0]->CompleteNow(net::OK);
+ // Check that each call invoked the callback with the right parameters.
- // 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(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(url3, resolver->pending_requests()[0]->url());
+ EXPECT_EQ(msg2.get(), result2->reply_msg);
+ EXPECT_EQ(net::OK, result2->error_code);
+ EXPECT_EQ("PROXY www.google2.com:80", result2->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();
+ EXPECT_EQ(msg3.get(), result3->reply_msg);
+ EXPECT_EQ(net::OK, result3->error_code);
+ EXPECT_EQ("PROXY www.google3.com:80", result3->proxy_list);
}
// Delete the helper while a request is in progress, and others are pending.
TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) {
- net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver;
- net::ProxyService service(new MockProxyConfigService, resolver);
-
- MyDelegate delegate;
- scoped_ptr<ResolveProxyMsgHelper> helper(
- new ResolveProxyMsgHelper(&delegate, &service));
+ RunnerBridge runner;
GURL url1("http://www.google1.com/");
GURL url2("http://www.google2.com/");
@@ -198,32 +343,35 @@ TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) {
IPC::Message* msg2 = new IPC::Message();
IPC::Message* msg3 = new IPC::Message();
- // Start three requests. Since the proxy resolver is async, all the
- // requests will be pending.
+ // Make the next request block.
+ runner.proxy_resolver()->x->Block();
- helper->Start(url1, msg1);
+ // Start three requests; since the first one blocked, the other two should
+ // be pending.
- // Finish ProxyService's initialization.
- resolver->pending_set_pac_script_request()->CompleteNow(net::OK);
+ scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1));
+ scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2));
+ scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3));
- 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());
+ result3->WaitUntilStarted();
// Delete the underlying ResolveProxyMsgHelper -- this should cancel all
// the requests which are outstanding.
- helper.reset();
-
- // The pending requests sent to the proxy resolver should have been cancelled.
+ runner.DestroyAsyncRunner();
- EXPECT_EQ(0u, resolver->pending_requests().size());
+ // 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(NULL, delegate.pending_result());
+ // 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)));
// It should also be the case that msg1, msg2, msg3 were deleted by the
- // cancellation. (Else will show up as a leak in Purify/Valgrind).
+ // cancellation. (Else will show up as a leak in Purify).
}