Index: net/proxy/sync_host_resolver_bridge_unittest.cc |
diff --git a/net/proxy/sync_host_resolver_bridge_unittest.cc b/net/proxy/sync_host_resolver_bridge_unittest.cc |
deleted file mode 100644 |
index 81ec33ebec91f74fae4f719a655f9c810b97cae7..0000000000000000000000000000000000000000 |
--- a/net/proxy/sync_host_resolver_bridge_unittest.cc |
+++ /dev/null |
@@ -1,244 +0,0 @@ |
-// Copyright (c) 2012 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. |
- |
-#include "net/proxy/sync_host_resolver_bridge.h" |
- |
-#include "base/threading/thread.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "net/base/address_list.h" |
-#include "net/base/net_errors.h" |
-#include "net/base/net_log.h" |
-#include "net/proxy/multi_threaded_proxy_resolver.h" |
-#include "net/base/test_completion_callback.h" |
-#include "net/proxy/proxy_info.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-// TODO(eroman): This test should be moved into |
-// multi_threaded_proxy_resolver_unittest.cc. |
- |
-namespace net { |
- |
-namespace { |
- |
-// This implementation of HostResolver allows blocking until a resolve request |
-// has been received. The resolve requests it receives will never be completed. |
-class BlockableHostResolver : public HostResolver { |
- public: |
- BlockableHostResolver() |
- : event_(true, false), |
- was_request_cancelled_(false) { |
- } |
- |
- virtual int Resolve(const RequestInfo& info, |
- AddressList* addresses, |
- const CompletionCallback& callback, |
- RequestHandle* out_req, |
- const BoundNetLog& net_log) OVERRIDE { |
- EXPECT_FALSE(callback.is_null()); |
- EXPECT_TRUE(out_req); |
- *out_req = reinterpret_cast<RequestHandle*>(1); // Magic value. |
- |
- // Indicate to the caller that a request was received. |
- event_.Signal(); |
- |
- // We return ERR_IO_PENDING, as this request will NEVER be completed. |
- // Expectation is for the caller to later cancel the request. |
- return ERR_IO_PENDING; |
- } |
- |
- virtual int ResolveFromCache(const RequestInfo& info, |
- AddressList* addresses, |
- const BoundNetLog& net_log) OVERRIDE { |
- NOTIMPLEMENTED(); |
- return ERR_UNEXPECTED; |
- } |
- |
- virtual void CancelRequest(RequestHandle req) OVERRIDE { |
- EXPECT_EQ(reinterpret_cast<RequestHandle*>(1), req); |
- was_request_cancelled_ = true; |
- } |
- |
- // Waits until Resolve() has been called. |
- void WaitUntilRequestIsReceived() { |
- event_.Wait(); |
- } |
- |
- bool was_request_cancelled() const { |
- return was_request_cancelled_; |
- } |
- |
- private: |
- // Event to notify when a resolve request was received. |
- base::WaitableEvent event_; |
- bool was_request_cancelled_; |
-}; |
- |
-// This implementation of ProxyResolver simply does a synchronous resolve |
-// on |host_resolver| in response to GetProxyForURL(). |
-class SyncProxyResolver : public ProxyResolver { |
- public: |
- explicit SyncProxyResolver(SyncHostResolverBridge* host_resolver) |
- : ProxyResolver(false), host_resolver_(host_resolver) {} |
- |
- virtual int GetProxyForURL(const GURL& url, |
- ProxyInfo* results, |
- const CompletionCallback& callback, |
- RequestHandle* request, |
- const BoundNetLog& net_log) { |
- EXPECT_FALSE(!callback.is_null()); |
- EXPECT_FALSE(request); |
- |
- // Do a synchronous host resolve. |
- HostResolver::RequestInfo info(HostPortPair::FromURL(url)); |
- AddressList addresses; |
- int rv = host_resolver_->Resolve(info, &addresses, net_log); |
- |
- EXPECT_EQ(ERR_ABORTED, rv); |
- |
- return rv; |
- } |
- |
- virtual void CancelRequest(RequestHandle request) OVERRIDE { |
- NOTREACHED(); |
- } |
- |
- virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE { |
- NOTREACHED(); |
- return LOAD_STATE_IDLE; |
- } |
- |
- virtual LoadState GetLoadStateThreadSafe( |
- RequestHandle request) const OVERRIDE { |
- NOTREACHED(); |
- return LOAD_STATE_IDLE; |
- } |
- |
- virtual void Shutdown() OVERRIDE { |
- host_resolver_->Shutdown(); |
- } |
- |
- virtual void CancelSetPacScript() OVERRIDE { |
- NOTREACHED(); |
- } |
- |
- virtual int SetPacScript( |
- const scoped_refptr<ProxyResolverScriptData>& script_data, |
- const CompletionCallback& callback) OVERRIDE { |
- return OK; |
- } |
- |
- private: |
- SyncHostResolverBridge* const host_resolver_; |
-}; |
- |
-class SyncProxyResolverFactory : public ProxyResolverFactory { |
- public: |
- // Takes ownership of |sync_host_resolver|. |
- explicit SyncProxyResolverFactory(SyncHostResolverBridge* sync_host_resolver) |
- : ProxyResolverFactory(false), |
- sync_host_resolver_(sync_host_resolver) { |
- } |
- |
- virtual ProxyResolver* CreateProxyResolver() OVERRIDE { |
- return new SyncProxyResolver(sync_host_resolver_.get()); |
- } |
- |
- private: |
- const scoped_ptr<SyncHostResolverBridge> sync_host_resolver_; |
-}; |
- |
-// This helper thread is used to create the circumstances for the deadlock. |
-// It is analagous to the "IO thread" which would be main thread running the |
-// network stack. |
-class IOThread : public base::Thread { |
- public: |
- IOThread() : base::Thread("IO-thread") {} |
- |
- virtual ~IOThread() { |
- Stop(); |
- } |
- |
- BlockableHostResolver* async_resolver() { |
- return async_resolver_.get(); |
- } |
- |
- protected: |
- virtual void Init() OVERRIDE { |
- async_resolver_.reset(new BlockableHostResolver()); |
- |
- // Create a synchronous host resolver that operates the async host |
- // resolver on THIS thread. |
- SyncHostResolverBridge* sync_resolver = |
- new SyncHostResolverBridge(async_resolver_.get(), message_loop()); |
- |
- proxy_resolver_.reset( |
- new MultiThreadedProxyResolver( |
- new SyncProxyResolverFactory(sync_resolver), |
- 1u)); |
- |
- // Initialize the resolver. |
- TestCompletionCallback callback; |
- proxy_resolver_->SetPacScript(ProxyResolverScriptData::FromURL(GURL()), |
- callback.callback()); |
- EXPECT_EQ(OK, callback.WaitForResult()); |
- |
- // Start an asynchronous request to the proxy resolver |
- // (note that it will never complete). |
- proxy_resolver_->GetProxyForURL( |
- GURL("http://test/"), &results_, callback_.callback(), &request_, |
- BoundNetLog()); |
- } |
- |
- virtual void CleanUp() OVERRIDE { |
- // Cancel the outstanding request (note however that this will not |
- // unblock the PAC thread though). |
- proxy_resolver_->CancelRequest(request_); |
- |
- // Delete the single threaded proxy resolver. |
- proxy_resolver_.reset(); |
- |
- // (There may have been a completion posted back to origin thread, avoid |
- // leaking it by running). |
- MessageLoop::current()->RunUntilIdle(); |
- |
- // During the teardown sequence of the single threaded proxy resolver, |
- // the outstanding host resolve should have been cancelled. |
- EXPECT_TRUE(async_resolver_->was_request_cancelled()); |
- } |
- |
- private: |
- // This (async) host resolver will outlive the thread that is operating it |
- // synchronously. |
- scoped_ptr<BlockableHostResolver> async_resolver_; |
- |
- scoped_ptr<ProxyResolver> proxy_resolver_; |
- |
- // Data for the outstanding request to the single threaded proxy resolver. |
- TestCompletionCallback callback_; |
- ProxyInfo results_; |
- ProxyResolver::RequestHandle request_; |
-}; |
- |
-// Test that a deadlock does not happen during shutdown when a host resolve |
-// is outstanding on the SyncHostResolverBridge. |
-// This is a regression test for http://crbug.com/41244. |
-TEST(MultiThreadedProxyResolverTest, ShutdownIsCalledBeforeThreadJoin) { |
- IOThread io_thread; |
- base::Thread::Options options; |
- options.message_loop_type = MessageLoop::TYPE_IO; |
- ASSERT_TRUE(io_thread.StartWithOptions(options)); |
- |
- io_thread.async_resolver()->WaitUntilRequestIsReceived(); |
- |
- // Now upon exitting this scope, the IOThread is destroyed -- this will |
- // stop the IOThread, which will in turn delete the |
- // SingleThreadedProxyResolver, which in turn will stop its internal |
- // PAC thread (which is currently blocked waiting on the host resolve which |
- // is running on IOThread). The IOThread::Cleanup() will verify that after |
- // the PAC thread is stopped, it cancels the request on the HostResolver. |
-} |
- |
-} // namespace |
- |
-} // namespace net |