OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/net/resolve_proxy_msg_helper.h" | 5 #include "chrome/browser/net/resolve_proxy_msg_helper.h" |
6 | 6 |
7 #include "base/waitable_event.h" | 7 #include "base/waitable_event.h" |
8 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" |
| 9 #include "net/proxy/mock_proxy_resolver.h" |
9 #include "net/proxy/proxy_config_service.h" | 10 #include "net/proxy/proxy_config_service.h" |
10 #include "net/proxy/proxy_resolver.h" | |
11 #include "net/proxy/single_threaded_proxy_resolver.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
13 | 12 |
14 // This ProxyConfigService always returns "http://pac" as the PAC url to use. | 13 // This ProxyConfigService always returns "http://pac" as the PAC url to use. |
15 class MockProxyConfigService: public net::ProxyConfigService { | 14 class MockProxyConfigService : public net::ProxyConfigService { |
16 public: | 15 public: |
17 virtual int GetProxyConfig(net::ProxyConfig* results) { | 16 virtual int GetProxyConfig(net::ProxyConfig* results) { |
18 results->pac_url = GURL("http://pac"); | 17 results->pac_url = GURL("http://pac"); |
19 return net::OK; | 18 return net::OK; |
20 } | 19 } |
21 }; | 20 }; |
22 | 21 |
23 // This PAC resolver always returns the hostname of the query URL as the | 22 class MyDelegate : public ResolveProxyMsgHelper::Delegate { |
24 // proxy to use. The Block() method will make GetProxyForURL() hang until | |
25 // Unblock() is called. | |
26 class SyncMockProxyResolver : public net::ProxyResolver { | |
27 public: | 23 public: |
28 SyncMockProxyResolver() : ProxyResolver(false /*expects_pac_bytes*/), | 24 struct PendingResult { |
29 event_(false, false), | 25 PendingResult(IPC::Message* msg, |
30 is_blocked_(false) { | 26 int error_code, |
| 27 const std::string& proxy_list) |
| 28 : msg(msg), error_code(error_code), proxy_list(proxy_list) { |
| 29 } |
| 30 |
| 31 IPC::Message* msg; |
| 32 int error_code; |
| 33 std::string proxy_list; |
| 34 }; |
| 35 |
| 36 // ResolveProxyMsgHelper::Delegate implementation: |
| 37 virtual void OnResolveProxyCompleted(IPC::Message* reply_msg, |
| 38 int error_code, |
| 39 const std::string& proxy_list) { |
| 40 DCHECK(!pending_result_.get()); |
| 41 pending_result_.reset(new PendingResult(reply_msg, error_code, proxy_list)); |
31 } | 42 } |
32 | 43 |
33 virtual int GetProxyForURL(const GURL& query_url, | 44 const PendingResult* pending_result() const { return pending_result_.get(); } |
34 net::ProxyInfo* results, | |
35 net::CompletionCallback* callback, | |
36 RequestHandle* request) { | |
37 if (is_blocked_) | |
38 event_.Wait(); | |
39 results->UseNamedProxy(query_url.host()); | |
40 return net::OK; | |
41 } | |
42 | 45 |
43 virtual void CancelRequest(RequestHandle request) { | 46 void clear_pending_result() { |
44 NOTREACHED(); | 47 pending_result_.reset(); |
45 } | |
46 | |
47 virtual int SetPacScript(const GURL& /*pac_url*/, | |
48 const std::string& /*bytes*/, | |
49 net::CompletionCallback* /*callback*/) { | |
50 return net::OK; | |
51 } | |
52 | |
53 void Block() { | |
54 is_blocked_ = true; | |
55 event_.Reset(); | |
56 } | |
57 | |
58 void Unblock() { | |
59 is_blocked_ = false; | |
60 event_.Signal(); | |
61 } | 48 } |
62 | 49 |
63 private: | 50 private: |
64 base::WaitableEvent event_; | 51 scoped_ptr<PendingResult> pending_result_; |
65 bool is_blocked_; | |
66 }; | 52 }; |
67 | 53 |
68 class MockProxyResolver : public net::SingleThreadedProxyResolver { | |
69 public: | |
70 MockProxyResolver() | |
71 : net::SingleThreadedProxyResolver(new SyncMockProxyResolver) { | |
72 x = reinterpret_cast<SyncMockProxyResolver*>(resolver()); | |
73 } | |
74 | |
75 // TODO(eroman): cleanup. | |
76 SyncMockProxyResolver* x; | |
77 }; | |
78 | |
79 // This struct holds the values that were passed to | |
80 // Delegate::OnResolveProxyCompleted(). The caller should use WaitUntilDone() | |
81 // to block until the result has been populated. | |
82 struct ResultFuture { | |
83 public: | |
84 ResultFuture() | |
85 : reply_msg(NULL), | |
86 error_code(0), | |
87 started_(false, false), | |
88 completed_(false, false) { | |
89 } | |
90 | |
91 // Wait until the request has completed. In other words we have invoked: | |
92 // ResolveProxyMsgHelper::Delegate::OnResolveProxyCompleted. | |
93 void WaitUntilDone() { | |
94 completed_.Wait(); | |
95 } | |
96 | |
97 // Wait until the request has been sent to ResolveProxyMsgHelper. | |
98 void WaitUntilStarted() { | |
99 started_.Wait(); | |
100 } | |
101 | |
102 bool TimedWaitUntilDone(const base::TimeDelta& max_time) { | |
103 return completed_.TimedWait(max_time); | |
104 } | |
105 | |
106 // These fields are only valid after returning from WaitUntilDone(). | |
107 IPC::Message* reply_msg; | |
108 int error_code; | |
109 std::string proxy_list; | |
110 | |
111 private: | |
112 friend class AsyncRequestRunner; | |
113 base::WaitableEvent started_; | |
114 base::WaitableEvent completed_; | |
115 }; | |
116 | |
117 // This class lives on the io thread. It starts async requests using the | |
118 // class under test (ResolveProxyMsgHelper), and signals the result future on | |
119 // completion. | |
120 class AsyncRequestRunner : public ResolveProxyMsgHelper::Delegate { | |
121 public: | |
122 AsyncRequestRunner(net::ProxyService* proxy_service) { | |
123 resolve_proxy_msg_helper_.reset( | |
124 new ResolveProxyMsgHelper(this, proxy_service)); | |
125 } | |
126 | |
127 void Start(ResultFuture* future, const GURL& url, IPC::Message* reply_msg) { | |
128 futures_.push_back(future); | |
129 resolve_proxy_msg_helper_->Start(url, reply_msg); | |
130 | |
131 // Notify of request start. | |
132 future->started_.Signal(); | |
133 } | |
134 | |
135 virtual void OnResolveProxyCompleted(IPC::Message* reply_msg, | |
136 int error_code, | |
137 const std::string& proxy_list) { | |
138 // Update the result future for this request (top of queue), and signal it. | |
139 ResultFuture* future = futures_.front(); | |
140 futures_.pop_front(); | |
141 | |
142 future->reply_msg = reply_msg; | |
143 future->error_code = error_code; | |
144 future->proxy_list = proxy_list; | |
145 | |
146 // Notify of request completion. | |
147 future->completed_.Signal(); | |
148 } | |
149 | |
150 private: | |
151 std::deque<ResultFuture*> futures_; | |
152 scoped_ptr<ResolveProxyMsgHelper> resolve_proxy_msg_helper_; | |
153 }; | |
154 | |
155 // Helper class to start async requests on an io thread, and return a | |
156 // result future. The caller then uses ResultFuture::WaitUntilDone() to | |
157 // get at the results. It "bridges" the originating thread with the helper | |
158 // io thread. | |
159 class RunnerBridge { | |
160 public: | |
161 RunnerBridge() : io_thread_("io_thread"), done_(false, false) { | |
162 // Start an io thread where we will run the async requests. | |
163 base::Thread::Options options; | |
164 options.message_loop_type = MessageLoop::TYPE_IO; | |
165 io_thread_.StartWithOptions(options); | |
166 | |
167 // Construct the state that lives on io thread. | |
168 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
169 this, &RunnerBridge::DoConstruct)); | |
170 done_.Wait(); | |
171 } | |
172 | |
173 // Start an async request on the io thread. | |
174 ResultFuture* Start(const GURL& url, IPC::Message* reply_msg) { | |
175 ResultFuture* future = new ResultFuture(); | |
176 | |
177 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
178 async_runner_, &AsyncRequestRunner::Start, future, url, reply_msg)); | |
179 | |
180 return future; | |
181 } | |
182 | |
183 void DestroyAsyncRunner() { | |
184 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
185 this, &RunnerBridge::DoDestroyAsyncRunner)); | |
186 done_.Wait(); | |
187 } | |
188 | |
189 ~RunnerBridge() { | |
190 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
191 this, &RunnerBridge::DoDestroy)); | |
192 done_.Wait(); | |
193 } | |
194 | |
195 MockProxyResolver* proxy_resolver() { | |
196 return proxy_resolver_; | |
197 } | |
198 | |
199 // Called from io thread. | |
200 void DoConstruct() { | |
201 proxy_resolver_ = new MockProxyResolver(); | |
202 proxy_service_ = new net::ProxyService(new MockProxyConfigService(), | |
203 proxy_resolver_); | |
204 async_runner_ = new AsyncRequestRunner(proxy_service_); | |
205 done_.Signal(); | |
206 } | |
207 | |
208 // Called from io thread. | |
209 void DoDestroy() { | |
210 delete async_runner_; | |
211 delete proxy_service_; | |
212 done_.Signal(); | |
213 } | |
214 | |
215 // Called from io thread. | |
216 void DoDestroyAsyncRunner() { | |
217 delete async_runner_; | |
218 async_runner_ = NULL; | |
219 done_.Signal(); | |
220 } | |
221 | |
222 private: | |
223 base::Thread io_thread_; | |
224 base::WaitableEvent done_; | |
225 | |
226 net::ProxyService* proxy_service_; | |
227 MockProxyResolver* proxy_resolver_; // Owned by proxy_service_. | |
228 | |
229 AsyncRequestRunner* async_runner_; | |
230 }; | |
231 | |
232 // Avoid the need to have an AddRef / Release | |
233 template<> | |
234 void RunnableMethodTraits<RunnerBridge>::RetainCallee(RunnerBridge*) {} | |
235 template<> | |
236 void RunnableMethodTraits<RunnerBridge>::ReleaseCallee(RunnerBridge*) {} | |
237 | |
238 template<> | |
239 void RunnableMethodTraits<AsyncRequestRunner>::RetainCallee( | |
240 AsyncRequestRunner*) {} | |
241 template<> | |
242 void RunnableMethodTraits<AsyncRequestRunner>::ReleaseCallee( | |
243 AsyncRequestRunner*) {} | |
244 | |
245 | |
246 // Issue three sequential requests -- each should succeed. | 54 // Issue three sequential requests -- each should succeed. |
247 TEST(ResolveProxyMsgHelperTest, Sequential) { | 55 TEST(ResolveProxyMsgHelperTest, Sequential) { |
248 RunnerBridge runner; | 56 net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver; |
| 57 net::ProxyService service(new MockProxyConfigService, resolver); |
| 58 |
| 59 MyDelegate delegate; |
| 60 ResolveProxyMsgHelper helper(&delegate, &service); |
249 | 61 |
250 GURL url1("http://www.google1.com/"); | 62 GURL url1("http://www.google1.com/"); |
251 GURL url2("http://www.google2.com/"); | 63 GURL url2("http://www.google2.com/"); |
252 GURL url3("http://www.google3.com/"); | 64 GURL url3("http://www.google3.com/"); |
253 | 65 |
254 scoped_ptr<IPC::Message> msg1(new IPC::Message()); | 66 scoped_ptr<IPC::Message> msg1(new IPC::Message()); |
255 scoped_ptr<IPC::Message> msg2(new IPC::Message()); | 67 scoped_ptr<IPC::Message> msg2(new IPC::Message()); |
256 scoped_ptr<IPC::Message> msg3(new IPC::Message()); | 68 scoped_ptr<IPC::Message> msg3(new IPC::Message()); |
257 | 69 |
258 // Execute each request sequentially (so there are never 2 requests | 70 // Execute each request sequentially (so there are never 2 requests |
259 // outstanding at the same time). | 71 // outstanding at the same time). |
260 | 72 |
261 scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get())); | 73 helper.Start(url1, msg1.get()); |
262 result1->WaitUntilDone(); | |
263 | 74 |
264 scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get())); | 75 // Finish ProxyService's initialization. |
265 result2->WaitUntilDone(); | 76 resolver->pending_set_pac_script_request()->CompleteNow(net::OK); |
266 | 77 |
267 scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get())); | 78 ASSERT_EQ(1u, resolver->pending_requests().size()); |
268 result3->WaitUntilDone(); | 79 EXPECT_EQ(url1, resolver->pending_requests()[0]->url()); |
| 80 resolver->pending_requests()[0]->results()->UseNamedProxy("result1:80"); |
| 81 resolver->pending_requests()[0]->CompleteNow(net::OK); |
269 | 82 |
270 // Check that each request gave the expected result. | 83 // Check result. |
| 84 EXPECT_EQ(msg1.get(), delegate.pending_result()->msg); |
| 85 EXPECT_EQ(net::OK, delegate.pending_result()->error_code); |
| 86 EXPECT_EQ("PROXY result1:80", delegate.pending_result()->proxy_list); |
| 87 delegate.clear_pending_result(); |
271 | 88 |
272 EXPECT_EQ(msg1.get(), result1->reply_msg); | 89 helper.Start(url2, msg2.get()); |
273 EXPECT_EQ(net::OK, result1->error_code); | |
274 EXPECT_EQ("PROXY www.google1.com:80", result1->proxy_list); | |
275 | 90 |
276 EXPECT_EQ(msg2.get(), result2->reply_msg); | 91 ASSERT_EQ(1u, resolver->pending_requests().size()); |
277 EXPECT_EQ(net::OK, result2->error_code); | 92 EXPECT_EQ(url2, resolver->pending_requests()[0]->url()); |
278 EXPECT_EQ("PROXY www.google2.com:80", result2->proxy_list); | 93 resolver->pending_requests()[0]->results()->UseNamedProxy("result2:80"); |
| 94 resolver->pending_requests()[0]->CompleteNow(net::OK); |
279 | 95 |
280 EXPECT_EQ(msg3.get(), result3->reply_msg); | 96 // Check result. |
281 EXPECT_EQ(net::OK, result3->error_code); | 97 EXPECT_EQ(msg2.get(), delegate.pending_result()->msg); |
282 EXPECT_EQ("PROXY www.google3.com:80", result3->proxy_list); | 98 EXPECT_EQ(net::OK, delegate.pending_result()->error_code); |
| 99 EXPECT_EQ("PROXY result2:80", delegate.pending_result()->proxy_list); |
| 100 delegate.clear_pending_result(); |
| 101 |
| 102 helper.Start(url3, msg3.get()); |
| 103 |
| 104 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 105 EXPECT_EQ(url3, resolver->pending_requests()[0]->url()); |
| 106 resolver->pending_requests()[0]->results()->UseNamedProxy("result3:80"); |
| 107 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 108 |
| 109 // Check result. |
| 110 EXPECT_EQ(msg3.get(), delegate.pending_result()->msg); |
| 111 EXPECT_EQ(net::OK, delegate.pending_result()->error_code); |
| 112 EXPECT_EQ("PROXY result3:80", delegate.pending_result()->proxy_list); |
| 113 delegate.clear_pending_result(); |
283 } | 114 } |
284 | 115 |
285 // Issue a request while one is already in progress -- should be queued. | 116 // Issue a request while one is already in progress -- should be queued. |
286 TEST(ResolveProxyMsgHelperTest, QueueRequests) { | 117 TEST(ResolveProxyMsgHelperTest, QueueRequests) { |
287 RunnerBridge runner; | 118 net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver; |
| 119 net::ProxyService service(new MockProxyConfigService, resolver); |
| 120 |
| 121 MyDelegate delegate; |
| 122 ResolveProxyMsgHelper helper(&delegate, &service); |
288 | 123 |
289 GURL url1("http://www.google1.com/"); | 124 GURL url1("http://www.google1.com/"); |
290 GURL url2("http://www.google2.com/"); | 125 GURL url2("http://www.google2.com/"); |
291 GURL url3("http://www.google3.com/"); | 126 GURL url3("http://www.google3.com/"); |
292 | 127 |
293 scoped_ptr<IPC::Message> msg1(new IPC::Message()); | 128 scoped_ptr<IPC::Message> msg1(new IPC::Message()); |
294 scoped_ptr<IPC::Message> msg2(new IPC::Message()); | 129 scoped_ptr<IPC::Message> msg2(new IPC::Message()); |
295 scoped_ptr<IPC::Message> msg3(new IPC::Message()); | 130 scoped_ptr<IPC::Message> msg3(new IPC::Message()); |
296 | 131 |
297 // Make the proxy resolver hang on the next request. | 132 // Start three requests. Since the proxy resolver is async, all the |
298 runner.proxy_resolver()->x->Block(); | 133 // requests will be pending. |
299 | 134 |
300 // Start three requests. Since the proxy resolver is hung, the second two | 135 helper.Start(url1, msg1.get()); |
301 // will be pending. | |
302 | 136 |
303 scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1.get())); | 137 // Finish ProxyService's initialization. |
304 scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2.get())); | 138 resolver->pending_set_pac_script_request()->CompleteNow(net::OK); |
305 scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3.get())); | |
306 | 139 |
307 // Wait for the final request to have been scheduled. Otherwise we may rush | 140 helper.Start(url2, msg2.get()); |
308 // to calling Unblock() without actually having blocked anything. | 141 helper.Start(url3, msg3.get()); |
309 result3->WaitUntilStarted(); | |
310 | 142 |
311 // Unblock the proxy service so requests 1-3 can complete. | 143 // ResolveProxyHelper only keeps 1 request outstanding in ProxyService |
312 runner.proxy_resolver()->x->Unblock(); | 144 // at a time. |
| 145 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 146 EXPECT_EQ(url1, resolver->pending_requests()[0]->url()); |
313 | 147 |
314 // Wait for all the requests to finish (they run in FIFO order). | 148 resolver->pending_requests()[0]->results()->UseNamedProxy("result1:80"); |
315 result3->WaitUntilDone(); | 149 resolver->pending_requests()[0]->CompleteNow(net::OK); |
316 | 150 |
317 // Check that each call invoked the callback with the right parameters. | 151 // Check result. |
| 152 EXPECT_EQ(msg1.get(), delegate.pending_result()->msg); |
| 153 EXPECT_EQ(net::OK, delegate.pending_result()->error_code); |
| 154 EXPECT_EQ("PROXY result1:80", delegate.pending_result()->proxy_list); |
| 155 delegate.clear_pending_result(); |
318 | 156 |
319 EXPECT_EQ(msg1.get(), result1->reply_msg); | 157 ASSERT_EQ(1u, resolver->pending_requests().size()); |
320 EXPECT_EQ(net::OK, result1->error_code); | 158 EXPECT_EQ(url2, resolver->pending_requests()[0]->url()); |
321 EXPECT_EQ("PROXY www.google1.com:80", result1->proxy_list); | |
322 | 159 |
323 EXPECT_EQ(msg2.get(), result2->reply_msg); | 160 resolver->pending_requests()[0]->results()->UseNamedProxy("result2:80"); |
324 EXPECT_EQ(net::OK, result2->error_code); | 161 resolver->pending_requests()[0]->CompleteNow(net::OK); |
325 EXPECT_EQ("PROXY www.google2.com:80", result2->proxy_list); | |
326 | 162 |
327 EXPECT_EQ(msg3.get(), result3->reply_msg); | 163 // Check result. |
328 EXPECT_EQ(net::OK, result3->error_code); | 164 EXPECT_EQ(msg2.get(), delegate.pending_result()->msg); |
329 EXPECT_EQ("PROXY www.google3.com:80", result3->proxy_list); | 165 EXPECT_EQ(net::OK, delegate.pending_result()->error_code); |
| 166 EXPECT_EQ("PROXY result2:80", delegate.pending_result()->proxy_list); |
| 167 delegate.clear_pending_result(); |
| 168 |
| 169 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 170 EXPECT_EQ(url3, resolver->pending_requests()[0]->url()); |
| 171 |
| 172 resolver->pending_requests()[0]->results()->UseNamedProxy("result3:80"); |
| 173 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 174 |
| 175 // Check result. |
| 176 EXPECT_EQ(msg3.get(), delegate.pending_result()->msg); |
| 177 EXPECT_EQ(net::OK, delegate.pending_result()->error_code); |
| 178 EXPECT_EQ("PROXY result3:80", delegate.pending_result()->proxy_list); |
| 179 delegate.clear_pending_result(); |
330 } | 180 } |
331 | 181 |
332 // Delete the helper while a request is in progress, and others are pending. | 182 // Delete the helper while a request is in progress, and others are pending. |
333 TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) { | 183 TEST(ResolveProxyMsgHelperTest, CancelPendingRequests) { |
334 RunnerBridge runner; | 184 net::MockAsyncProxyResolver* resolver = new net::MockAsyncProxyResolver; |
| 185 net::ProxyService service(new MockProxyConfigService, resolver); |
| 186 |
| 187 MyDelegate delegate; |
| 188 scoped_ptr<ResolveProxyMsgHelper> helper( |
| 189 new ResolveProxyMsgHelper(&delegate, &service)); |
335 | 190 |
336 GURL url1("http://www.google1.com/"); | 191 GURL url1("http://www.google1.com/"); |
337 GURL url2("http://www.google2.com/"); | 192 GURL url2("http://www.google2.com/"); |
338 GURL url3("http://www.google3.com/"); | 193 GURL url3("http://www.google3.com/"); |
339 | 194 |
340 // NOTE: these are not scoped ptr, since they will be deleted by the | 195 // NOTE: these are not scoped ptr, since they will be deleted by the |
341 // request's cancellation. | 196 // request's cancellation. |
342 IPC::Message* msg1 = new IPC::Message(); | 197 IPC::Message* msg1 = new IPC::Message(); |
343 IPC::Message* msg2 = new IPC::Message(); | 198 IPC::Message* msg2 = new IPC::Message(); |
344 IPC::Message* msg3 = new IPC::Message(); | 199 IPC::Message* msg3 = new IPC::Message(); |
345 | 200 |
346 // Make the next request block. | 201 // Start three requests. Since the proxy resolver is async, all the |
347 runner.proxy_resolver()->x->Block(); | 202 // requests will be pending. |
348 | 203 |
349 // Start three requests; since the first one blocked, the other two should | 204 helper->Start(url1, msg1); |
350 // be pending. | |
351 | 205 |
352 scoped_ptr<ResultFuture> result1(runner.Start(url1, msg1)); | 206 // Finish ProxyService's initialization. |
353 scoped_ptr<ResultFuture> result2(runner.Start(url2, msg2)); | 207 resolver->pending_set_pac_script_request()->CompleteNow(net::OK); |
354 scoped_ptr<ResultFuture> result3(runner.Start(url3, msg3)); | |
355 | 208 |
356 result3->WaitUntilStarted(); | 209 helper->Start(url2, msg2); |
| 210 helper->Start(url3, msg3); |
| 211 |
| 212 // ResolveProxyHelper only keeps 1 request outstanding in ProxyService |
| 213 // at a time. |
| 214 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 215 EXPECT_EQ(url1, resolver->pending_requests()[0]->url()); |
357 | 216 |
358 // Delete the underlying ResolveProxyMsgHelper -- this should cancel all | 217 // Delete the underlying ResolveProxyMsgHelper -- this should cancel all |
359 // the requests which are outstanding. | 218 // the requests which are outstanding. |
360 runner.DestroyAsyncRunner(); | 219 helper.reset(); |
361 | 220 |
362 // Unblocking the proxy resolver means the three requests can complete -- | 221 // The pending requests sent to the proxy resolver should have been cancelled. |
363 // however they should not try to notify the delegate since we have already | |
364 // deleted the helper. | |
365 runner.proxy_resolver()->x->Unblock(); | |
366 | 222 |
367 // Check that none of the requests were sent to the delegate. | 223 EXPECT_EQ(0u, resolver->pending_requests().size()); |
368 EXPECT_FALSE( | 224 |
369 result1->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2))); | 225 EXPECT_EQ(NULL, delegate.pending_result()); |
370 EXPECT_FALSE( | |
371 result2->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2))); | |
372 EXPECT_FALSE( | |
373 result3->TimedWaitUntilDone(base::TimeDelta::FromMilliseconds(2))); | |
374 | 226 |
375 // It should also be the case that msg1, msg2, msg3 were deleted by the | 227 // It should also be the case that msg1, msg2, msg3 were deleted by the |
376 // cancellation. (Else will show up as a leak in Purify). | 228 // cancellation. (Else will show up as a leak in Purify/Valgrind). |
377 } | 229 } |
OLD | NEW |