diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-06 05:42:11 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-06 05:42:11 +0000 |
commit | 550dd1ae4b01d438a9d8e46e5069de600f0f648f (patch) | |
tree | 76de85cfaf2b4b64b1ebd65b6d8bda57e6943c20 /chrome/browser/net | |
parent | a1353855e56d0154af127b9cb6df95287a4d5be5 (diff) | |
download | chromium_src-550dd1ae4b01d438a9d8e46e5069de600f0f648f.zip chromium_src-550dd1ae4b01d438a9d8e46e5069de600f0f648f.tar.gz chromium_src-550dd1ae4b01d438a9d8e46e5069de600f0f648f.tar.bz2 |
Remove dependency on SingleThreadedProxyResolver from resolve_proxy_msg_helper_unittest.cc.
Extracts MockAsyncProxyResolver to "mock_proxy_resolver.h".
This should be the last unittest that needs cleanup post r21631.
BUG=http://crbug.com/11079
Review URL: http://codereview.chromium.org/160619
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22591 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/net')
-rw-r--r-- | chrome/browser/net/resolve_proxy_msg_helper_unittest.cc | 408 |
1 files changed, 130 insertions, 278 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). } |