Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(416)

Side by Side Diff: net/proxy/sync_host_resolver_bridge_unittest.cc

Issue 11885009: Improve performance of proxy resolver by tracing DNS dependencies. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase off trunk Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/proxy/sync_host_resolver_bridge.h"
6
7 #include "base/threading/thread.h"
8 #include "base/synchronization/waitable_event.h"
9 #include "net/base/address_list.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/net_log.h"
12 #include "net/proxy/multi_threaded_proxy_resolver.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/proxy/proxy_info.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 // TODO(eroman): This test should be moved into
18 // multi_threaded_proxy_resolver_unittest.cc.
19
20 namespace net {
21
22 namespace {
23
24 // This implementation of HostResolver allows blocking until a resolve request
25 // has been received. The resolve requests it receives will never be completed.
26 class BlockableHostResolver : public HostResolver {
27 public:
28 BlockableHostResolver()
29 : event_(true, false),
30 was_request_cancelled_(false) {
31 }
32
33 virtual int Resolve(const RequestInfo& info,
34 AddressList* addresses,
35 const CompletionCallback& callback,
36 RequestHandle* out_req,
37 const BoundNetLog& net_log) OVERRIDE {
38 EXPECT_FALSE(callback.is_null());
39 EXPECT_TRUE(out_req);
40 *out_req = reinterpret_cast<RequestHandle*>(1); // Magic value.
41
42 // Indicate to the caller that a request was received.
43 event_.Signal();
44
45 // We return ERR_IO_PENDING, as this request will NEVER be completed.
46 // Expectation is for the caller to later cancel the request.
47 return ERR_IO_PENDING;
48 }
49
50 virtual int ResolveFromCache(const RequestInfo& info,
51 AddressList* addresses,
52 const BoundNetLog& net_log) OVERRIDE {
53 NOTIMPLEMENTED();
54 return ERR_UNEXPECTED;
55 }
56
57 virtual void CancelRequest(RequestHandle req) OVERRIDE {
58 EXPECT_EQ(reinterpret_cast<RequestHandle*>(1), req);
59 was_request_cancelled_ = true;
60 }
61
62 // Waits until Resolve() has been called.
63 void WaitUntilRequestIsReceived() {
64 event_.Wait();
65 }
66
67 bool was_request_cancelled() const {
68 return was_request_cancelled_;
69 }
70
71 private:
72 // Event to notify when a resolve request was received.
73 base::WaitableEvent event_;
74 bool was_request_cancelled_;
75 };
76
77 // This implementation of ProxyResolver simply does a synchronous resolve
78 // on |host_resolver| in response to GetProxyForURL().
79 class SyncProxyResolver : public ProxyResolver {
80 public:
81 explicit SyncProxyResolver(SyncHostResolverBridge* host_resolver)
82 : ProxyResolver(false), host_resolver_(host_resolver) {}
83
84 virtual int GetProxyForURL(const GURL& url,
85 ProxyInfo* results,
86 const CompletionCallback& callback,
87 RequestHandle* request,
88 const BoundNetLog& net_log) {
89 EXPECT_FALSE(!callback.is_null());
90 EXPECT_FALSE(request);
91
92 // Do a synchronous host resolve.
93 HostResolver::RequestInfo info(HostPortPair::FromURL(url));
94 AddressList addresses;
95 int rv = host_resolver_->Resolve(info, &addresses, net_log);
96
97 EXPECT_EQ(ERR_ABORTED, rv);
98
99 return rv;
100 }
101
102 virtual void CancelRequest(RequestHandle request) OVERRIDE {
103 NOTREACHED();
104 }
105
106 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
107 NOTREACHED();
108 return LOAD_STATE_IDLE;
109 }
110
111 virtual LoadState GetLoadStateThreadSafe(
112 RequestHandle request) const OVERRIDE {
113 NOTREACHED();
114 return LOAD_STATE_IDLE;
115 }
116
117 virtual void Shutdown() OVERRIDE {
118 host_resolver_->Shutdown();
119 }
120
121 virtual void CancelSetPacScript() OVERRIDE {
122 NOTREACHED();
123 }
124
125 virtual int SetPacScript(
126 const scoped_refptr<ProxyResolverScriptData>& script_data,
127 const CompletionCallback& callback) OVERRIDE {
128 return OK;
129 }
130
131 private:
132 SyncHostResolverBridge* const host_resolver_;
133 };
134
135 class SyncProxyResolverFactory : public ProxyResolverFactory {
136 public:
137 // Takes ownership of |sync_host_resolver|.
138 explicit SyncProxyResolverFactory(SyncHostResolverBridge* sync_host_resolver)
139 : ProxyResolverFactory(false),
140 sync_host_resolver_(sync_host_resolver) {
141 }
142
143 virtual ProxyResolver* CreateProxyResolver() OVERRIDE {
144 return new SyncProxyResolver(sync_host_resolver_.get());
145 }
146
147 private:
148 const scoped_ptr<SyncHostResolverBridge> sync_host_resolver_;
149 };
150
151 // This helper thread is used to create the circumstances for the deadlock.
152 // It is analagous to the "IO thread" which would be main thread running the
153 // network stack.
154 class IOThread : public base::Thread {
155 public:
156 IOThread() : base::Thread("IO-thread") {}
157
158 virtual ~IOThread() {
159 Stop();
160 }
161
162 BlockableHostResolver* async_resolver() {
163 return async_resolver_.get();
164 }
165
166 protected:
167 virtual void Init() OVERRIDE {
168 async_resolver_.reset(new BlockableHostResolver());
169
170 // Create a synchronous host resolver that operates the async host
171 // resolver on THIS thread.
172 SyncHostResolverBridge* sync_resolver =
173 new SyncHostResolverBridge(async_resolver_.get(), message_loop());
174
175 proxy_resolver_.reset(
176 new MultiThreadedProxyResolver(
177 new SyncProxyResolverFactory(sync_resolver),
178 1u));
179
180 // Initialize the resolver.
181 TestCompletionCallback callback;
182 proxy_resolver_->SetPacScript(ProxyResolverScriptData::FromURL(GURL()),
183 callback.callback());
184 EXPECT_EQ(OK, callback.WaitForResult());
185
186 // Start an asynchronous request to the proxy resolver
187 // (note that it will never complete).
188 proxy_resolver_->GetProxyForURL(
189 GURL("http://test/"), &results_, callback_.callback(), &request_,
190 BoundNetLog());
191 }
192
193 virtual void CleanUp() OVERRIDE {
194 // Cancel the outstanding request (note however that this will not
195 // unblock the PAC thread though).
196 proxy_resolver_->CancelRequest(request_);
197
198 // Delete the single threaded proxy resolver.
199 proxy_resolver_.reset();
200
201 // (There may have been a completion posted back to origin thread, avoid
202 // leaking it by running).
203 MessageLoop::current()->RunUntilIdle();
204
205 // During the teardown sequence of the single threaded proxy resolver,
206 // the outstanding host resolve should have been cancelled.
207 EXPECT_TRUE(async_resolver_->was_request_cancelled());
208 }
209
210 private:
211 // This (async) host resolver will outlive the thread that is operating it
212 // synchronously.
213 scoped_ptr<BlockableHostResolver> async_resolver_;
214
215 scoped_ptr<ProxyResolver> proxy_resolver_;
216
217 // Data for the outstanding request to the single threaded proxy resolver.
218 TestCompletionCallback callback_;
219 ProxyInfo results_;
220 ProxyResolver::RequestHandle request_;
221 };
222
223 // Test that a deadlock does not happen during shutdown when a host resolve
224 // is outstanding on the SyncHostResolverBridge.
225 // This is a regression test for http://crbug.com/41244.
226 TEST(MultiThreadedProxyResolverTest, ShutdownIsCalledBeforeThreadJoin) {
227 IOThread io_thread;
228 base::Thread::Options options;
229 options.message_loop_type = MessageLoop::TYPE_IO;
230 ASSERT_TRUE(io_thread.StartWithOptions(options));
231
232 io_thread.async_resolver()->WaitUntilRequestIsReceived();
233
234 // Now upon exitting this scope, the IOThread is destroyed -- this will
235 // stop the IOThread, which will in turn delete the
236 // SingleThreadedProxyResolver, which in turn will stop its internal
237 // PAC thread (which is currently blocked waiting on the host resolve which
238 // is running on IOThread). The IOThread::Cleanup() will verify that after
239 // the PAC thread is stopped, it cancels the request on the HostResolver.
240 }
241
242 } // namespace
243
244 } // namespace net
OLDNEW
« net/proxy/proxy_resolver_v8_tracing_unittest.cc ('K') | « net/proxy/sync_host_resolver_bridge.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698