OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "net/proxy/multi_threaded_proxy_resolver.h" | 5 #include "net/proxy/multi_threaded_proxy_resolver.h" |
6 | 6 |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 | 51 |
52 // Write something into |net_log| (doesn't really have any meaning.) | 52 // Write something into |net_log| (doesn't really have any meaning.) |
53 net_log.BeginEvent(NetLog::TYPE_PAC_JAVASCRIPT_ALERT); | 53 net_log.BeginEvent(NetLog::TYPE_PAC_JAVASCRIPT_ALERT); |
54 | 54 |
55 results->UseNamedProxy(query_url.host()); | 55 results->UseNamedProxy(query_url.host()); |
56 | 56 |
57 // Return a success code which represents the request's order. | 57 // Return a success code which represents the request's order. |
58 return request_count_++; | 58 return request_count_++; |
59 } | 59 } |
60 | 60 |
61 virtual void CancelRequest(RequestHandle request) OVERRIDE { | 61 virtual void CancelRequest(RequestHandle request) OVERRIDE { NOTREACHED(); } |
62 NOTREACHED(); | |
63 } | |
64 | 62 |
65 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE { | 63 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE { |
66 NOTREACHED(); | 64 NOTREACHED(); |
67 return LOAD_STATE_IDLE; | 65 return LOAD_STATE_IDLE; |
68 } | 66 } |
69 | 67 |
70 virtual void CancelSetPacScript() OVERRIDE { | 68 virtual void CancelSetPacScript() OVERRIDE { NOTREACHED(); } |
71 NOTREACHED(); | |
72 } | |
73 | 69 |
74 virtual int SetPacScript( | 70 virtual int SetPacScript( |
75 const scoped_refptr<ProxyResolverScriptData>& script_data, | 71 const scoped_refptr<ProxyResolverScriptData>& script_data, |
76 const CompletionCallback& callback) OVERRIDE { | 72 const CompletionCallback& callback) OVERRIDE { |
77 CheckIsOnWorkerThread(); | 73 CheckIsOnWorkerThread(); |
78 last_script_data_ = script_data; | 74 last_script_data_ = script_data; |
79 return OK; | 75 return OK; |
80 } | 76 } |
81 | 77 |
82 int request_count() const { return request_count_; } | 78 int request_count() const { return request_count_; } |
(...skipping 14 matching lines...) Expand all Loading... |
97 // test, so at least make sure it isn't the main loop. | 93 // test, so at least make sure it isn't the main loop. |
98 EXPECT_NE(base::MessageLoop::current(), wrong_loop_); | 94 EXPECT_NE(base::MessageLoop::current(), wrong_loop_); |
99 } | 95 } |
100 | 96 |
101 base::MessageLoop* wrong_loop_; | 97 base::MessageLoop* wrong_loop_; |
102 int request_count_; | 98 int request_count_; |
103 scoped_refptr<ProxyResolverScriptData> last_script_data_; | 99 scoped_refptr<ProxyResolverScriptData> last_script_data_; |
104 base::TimeDelta resolve_latency_; | 100 base::TimeDelta resolve_latency_; |
105 }; | 101 }; |
106 | 102 |
107 | |
108 // A mock synchronous ProxyResolver which can be set to block upon reaching | 103 // A mock synchronous ProxyResolver which can be set to block upon reaching |
109 // GetProxyForURL(). | 104 // GetProxyForURL(). |
110 // TODO(eroman): WaitUntilBlocked() *must* be called before calling Unblock(), | 105 // TODO(eroman): WaitUntilBlocked() *must* be called before calling Unblock(), |
111 // otherwise there will be a race on |should_block_| since it is | 106 // otherwise there will be a race on |should_block_| since it is |
112 // read without any synchronization. | 107 // read without any synchronization. |
113 class BlockableProxyResolver : public MockProxyResolver { | 108 class BlockableProxyResolver : public MockProxyResolver { |
114 public: | 109 public: |
115 BlockableProxyResolver() | 110 BlockableProxyResolver() |
116 : should_block_(false), | 111 : should_block_(false), unblocked_(true, true), blocked_(true, false) {} |
117 unblocked_(true, true), | |
118 blocked_(true, false) { | |
119 } | |
120 | 112 |
121 void Block() { | 113 void Block() { |
122 should_block_ = true; | 114 should_block_ = true; |
123 unblocked_.Reset(); | 115 unblocked_.Reset(); |
124 } | 116 } |
125 | 117 |
126 void Unblock() { | 118 void Unblock() { |
127 should_block_ = false; | 119 should_block_ = false; |
128 blocked_.Reset(); | 120 blocked_.Reset(); |
129 unblocked_.Signal(); | 121 unblocked_.Signal(); |
130 } | 122 } |
131 | 123 |
132 void WaitUntilBlocked() { | 124 void WaitUntilBlocked() { blocked_.Wait(); } |
133 blocked_.Wait(); | |
134 } | |
135 | 125 |
136 virtual int GetProxyForURL(const GURL& query_url, | 126 virtual int GetProxyForURL(const GURL& query_url, |
137 ProxyInfo* results, | 127 ProxyInfo* results, |
138 const CompletionCallback& callback, | 128 const CompletionCallback& callback, |
139 RequestHandle* request, | 129 RequestHandle* request, |
140 const BoundNetLog& net_log) OVERRIDE { | 130 const BoundNetLog& net_log) OVERRIDE { |
141 if (should_block_) { | 131 if (should_block_) { |
142 blocked_.Signal(); | 132 blocked_.Signal(); |
143 unblocked_.Wait(); | 133 unblocked_.Wait(); |
144 } | 134 } |
145 | 135 |
146 return MockProxyResolver::GetProxyForURL( | 136 return MockProxyResolver::GetProxyForURL( |
147 query_url, results, callback, request, net_log); | 137 query_url, results, callback, request, net_log); |
148 } | 138 } |
149 | 139 |
150 private: | 140 private: |
151 bool should_block_; | 141 bool should_block_; |
152 base::WaitableEvent unblocked_; | 142 base::WaitableEvent unblocked_; |
153 base::WaitableEvent blocked_; | 143 base::WaitableEvent blocked_; |
154 }; | 144 }; |
155 | 145 |
156 // ForwardingProxyResolver forwards all requests to |impl|. | 146 // ForwardingProxyResolver forwards all requests to |impl|. |
157 class ForwardingProxyResolver : public ProxyResolver { | 147 class ForwardingProxyResolver : public ProxyResolver { |
158 public: | 148 public: |
159 explicit ForwardingProxyResolver(ProxyResolver* impl) | 149 explicit ForwardingProxyResolver(ProxyResolver* impl) |
160 : ProxyResolver(impl->expects_pac_bytes()), | 150 : ProxyResolver(impl->expects_pac_bytes()), impl_(impl) {} |
161 impl_(impl) {} | |
162 | 151 |
163 virtual int GetProxyForURL(const GURL& query_url, | 152 virtual int GetProxyForURL(const GURL& query_url, |
164 ProxyInfo* results, | 153 ProxyInfo* results, |
165 const CompletionCallback& callback, | 154 const CompletionCallback& callback, |
166 RequestHandle* request, | 155 RequestHandle* request, |
167 const BoundNetLog& net_log) OVERRIDE { | 156 const BoundNetLog& net_log) OVERRIDE { |
168 return impl_->GetProxyForURL( | 157 return impl_->GetProxyForURL( |
169 query_url, results, callback, request, net_log); | 158 query_url, results, callback, request, net_log); |
170 } | 159 } |
171 | 160 |
172 virtual void CancelRequest(RequestHandle request) OVERRIDE { | 161 virtual void CancelRequest(RequestHandle request) OVERRIDE { |
173 impl_->CancelRequest(request); | 162 impl_->CancelRequest(request); |
174 } | 163 } |
175 | 164 |
176 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE { | 165 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE { |
177 NOTREACHED(); | 166 NOTREACHED(); |
178 return LOAD_STATE_IDLE; | 167 return LOAD_STATE_IDLE; |
179 } | 168 } |
180 | 169 |
181 virtual void CancelSetPacScript() OVERRIDE { | 170 virtual void CancelSetPacScript() OVERRIDE { impl_->CancelSetPacScript(); } |
182 impl_->CancelSetPacScript(); | |
183 } | |
184 | 171 |
185 virtual int SetPacScript( | 172 virtual int SetPacScript( |
186 const scoped_refptr<ProxyResolverScriptData>& script_data, | 173 const scoped_refptr<ProxyResolverScriptData>& script_data, |
187 const CompletionCallback& callback) OVERRIDE { | 174 const CompletionCallback& callback) OVERRIDE { |
188 return impl_->SetPacScript(script_data, callback); | 175 return impl_->SetPacScript(script_data, callback); |
189 } | 176 } |
190 | 177 |
191 private: | 178 private: |
192 ProxyResolver* impl_; | 179 ProxyResolver* impl_; |
193 }; | 180 }; |
(...skipping 12 matching lines...) Expand all Loading... |
206 | 193 |
207 private: | 194 private: |
208 ProxyResolver* resolver_; | 195 ProxyResolver* resolver_; |
209 }; | 196 }; |
210 | 197 |
211 // This factory returns new instances of BlockableProxyResolver. | 198 // This factory returns new instances of BlockableProxyResolver. |
212 class BlockableProxyResolverFactory : public ProxyResolverFactory { | 199 class BlockableProxyResolverFactory : public ProxyResolverFactory { |
213 public: | 200 public: |
214 BlockableProxyResolverFactory() : ProxyResolverFactory(true) {} | 201 BlockableProxyResolverFactory() : ProxyResolverFactory(true) {} |
215 | 202 |
216 virtual ~BlockableProxyResolverFactory() { | 203 virtual ~BlockableProxyResolverFactory() { STLDeleteElements(&resolvers_); } |
217 STLDeleteElements(&resolvers_); | |
218 } | |
219 | 204 |
220 virtual ProxyResolver* CreateProxyResolver() OVERRIDE { | 205 virtual ProxyResolver* CreateProxyResolver() OVERRIDE { |
221 BlockableProxyResolver* resolver = new BlockableProxyResolver; | 206 BlockableProxyResolver* resolver = new BlockableProxyResolver; |
222 resolvers_.push_back(resolver); | 207 resolvers_.push_back(resolver); |
223 return new ForwardingProxyResolver(resolver); | 208 return new ForwardingProxyResolver(resolver); |
224 } | 209 } |
225 | 210 |
226 std::vector<BlockableProxyResolver*> resolvers() { | 211 std::vector<BlockableProxyResolver*> resolvers() { return resolvers_; } |
227 return resolvers_; | |
228 } | |
229 | 212 |
230 private: | 213 private: |
231 std::vector<BlockableProxyResolver*> resolvers_; | 214 std::vector<BlockableProxyResolver*> resolvers_; |
232 }; | 215 }; |
233 | 216 |
234 TEST(MultiThreadedProxyResolverTest, SingleThread_Basic) { | 217 TEST(MultiThreadedProxyResolverTest, SingleThread_Basic) { |
235 const size_t kNumThreads = 1u; | 218 const size_t kNumThreads = 1u; |
236 scoped_ptr<MockProxyResolver> mock(new MockProxyResolver); | 219 scoped_ptr<MockProxyResolver> mock(new MockProxyResolver); |
237 MultiThreadedProxyResolver resolver( | 220 MultiThreadedProxyResolver resolver( |
238 new ForwardingProxyResolverFactory(mock.get()), kNumThreads); | 221 new ForwardingProxyResolverFactory(mock.get()), kNumThreads); |
(...skipping 10 matching lines...) Expand all Loading... |
249 set_script_callback.callback()); | 232 set_script_callback.callback()); |
250 EXPECT_EQ(ERR_IO_PENDING, rv); | 233 EXPECT_EQ(ERR_IO_PENDING, rv); |
251 EXPECT_EQ(OK, set_script_callback.WaitForResult()); | 234 EXPECT_EQ(OK, set_script_callback.WaitForResult()); |
252 EXPECT_EQ(ASCIIToUTF16("pac script bytes"), | 235 EXPECT_EQ(ASCIIToUTF16("pac script bytes"), |
253 mock->last_script_data()->utf16()); | 236 mock->last_script_data()->utf16()); |
254 | 237 |
255 // Start request 0. | 238 // Start request 0. |
256 TestCompletionCallback callback0; | 239 TestCompletionCallback callback0; |
257 CapturingBoundNetLog log0; | 240 CapturingBoundNetLog log0; |
258 ProxyInfo results0; | 241 ProxyInfo results0; |
259 rv = resolver.GetProxyForURL(GURL("http://request0"), &results0, | 242 rv = resolver.GetProxyForURL(GURL("http://request0"), |
260 callback0.callback(), NULL, log0.bound()); | 243 &results0, |
| 244 callback0.callback(), |
| 245 NULL, |
| 246 log0.bound()); |
261 EXPECT_EQ(ERR_IO_PENDING, rv); | 247 EXPECT_EQ(ERR_IO_PENDING, rv); |
262 | 248 |
263 // Wait for request 0 to finish. | 249 // Wait for request 0 to finish. |
264 rv = callback0.WaitForResult(); | 250 rv = callback0.WaitForResult(); |
265 EXPECT_EQ(0, rv); | 251 EXPECT_EQ(0, rv); |
266 EXPECT_EQ("PROXY request0:80", results0.ToPacString()); | 252 EXPECT_EQ("PROXY request0:80", results0.ToPacString()); |
267 | 253 |
268 // The mock proxy resolver should have written 1 log entry. And | 254 // The mock proxy resolver should have written 1 log entry. And |
269 // on completion, this should have been copied into |log0|. | 255 // on completion, this should have been copied into |log0|. |
270 // We also have 1 log entry that was emitted by the | 256 // We also have 1 log entry that was emitted by the |
271 // MultiThreadedProxyResolver. | 257 // MultiThreadedProxyResolver. |
272 CapturingNetLog::CapturedEntryList entries0; | 258 CapturingNetLog::CapturedEntryList entries0; |
273 log0.GetEntries(&entries0); | 259 log0.GetEntries(&entries0); |
274 | 260 |
275 ASSERT_EQ(2u, entries0.size()); | 261 ASSERT_EQ(2u, entries0.size()); |
276 EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, entries0[0].type); | 262 EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, entries0[0].type); |
277 | 263 |
278 // Start 3 more requests (request1 to request3). | 264 // Start 3 more requests (request1 to request3). |
279 | 265 |
280 TestCompletionCallback callback1; | 266 TestCompletionCallback callback1; |
281 ProxyInfo results1; | 267 ProxyInfo results1; |
282 rv = resolver.GetProxyForURL(GURL("http://request1"), &results1, | 268 rv = resolver.GetProxyForURL(GURL("http://request1"), |
283 callback1.callback(), NULL, BoundNetLog()); | 269 &results1, |
| 270 callback1.callback(), |
| 271 NULL, |
| 272 BoundNetLog()); |
284 EXPECT_EQ(ERR_IO_PENDING, rv); | 273 EXPECT_EQ(ERR_IO_PENDING, rv); |
285 | 274 |
286 TestCompletionCallback callback2; | 275 TestCompletionCallback callback2; |
287 ProxyInfo results2; | 276 ProxyInfo results2; |
288 rv = resolver.GetProxyForURL(GURL("http://request2"), &results2, | 277 rv = resolver.GetProxyForURL(GURL("http://request2"), |
289 callback2.callback(), NULL, BoundNetLog()); | 278 &results2, |
| 279 callback2.callback(), |
| 280 NULL, |
| 281 BoundNetLog()); |
290 EXPECT_EQ(ERR_IO_PENDING, rv); | 282 EXPECT_EQ(ERR_IO_PENDING, rv); |
291 | 283 |
292 TestCompletionCallback callback3; | 284 TestCompletionCallback callback3; |
293 ProxyInfo results3; | 285 ProxyInfo results3; |
294 rv = resolver.GetProxyForURL(GURL("http://request3"), &results3, | 286 rv = resolver.GetProxyForURL(GURL("http://request3"), |
295 callback3.callback(), NULL, BoundNetLog()); | 287 &results3, |
| 288 callback3.callback(), |
| 289 NULL, |
| 290 BoundNetLog()); |
296 EXPECT_EQ(ERR_IO_PENDING, rv); | 291 EXPECT_EQ(ERR_IO_PENDING, rv); |
297 | 292 |
298 // Wait for the requests to finish (they must finish in the order they were | 293 // Wait for the requests to finish (they must finish in the order they were |
299 // started, which is what we check for from their magic return value) | 294 // started, which is what we check for from their magic return value) |
300 | 295 |
301 rv = callback1.WaitForResult(); | 296 rv = callback1.WaitForResult(); |
302 EXPECT_EQ(1, rv); | 297 EXPECT_EQ(1, rv); |
303 EXPECT_EQ("PROXY request1:80", results1.ToPacString()); | 298 EXPECT_EQ("PROXY request1:80", results1.ToPacString()); |
304 | 299 |
305 rv = callback2.WaitForResult(); | 300 rv = callback2.WaitForResult(); |
306 EXPECT_EQ(2, rv); | 301 EXPECT_EQ(2, rv); |
307 EXPECT_EQ("PROXY request2:80", results2.ToPacString()); | 302 EXPECT_EQ("PROXY request2:80", results2.ToPacString()); |
308 | 303 |
309 rv = callback3.WaitForResult(); | 304 rv = callback3.WaitForResult(); |
310 EXPECT_EQ(3, rv); | 305 EXPECT_EQ(3, rv); |
311 EXPECT_EQ("PROXY request3:80", results3.ToPacString()); | 306 EXPECT_EQ("PROXY request3:80", results3.ToPacString()); |
312 } | 307 } |
313 | 308 |
314 // Tests that the NetLog is updated to include the time the request was waiting | 309 // Tests that the NetLog is updated to include the time the request was waiting |
315 // to be scheduled to a thread. | 310 // to be scheduled to a thread. |
316 TEST(MultiThreadedProxyResolverTest, | 311 TEST(MultiThreadedProxyResolverTest, SingleThread_UpdatesNetLogWithThreadWait) { |
317 SingleThread_UpdatesNetLogWithThreadWait) { | |
318 const size_t kNumThreads = 1u; | 312 const size_t kNumThreads = 1u; |
319 scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver); | 313 scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver); |
320 MultiThreadedProxyResolver resolver( | 314 MultiThreadedProxyResolver resolver( |
321 new ForwardingProxyResolverFactory(mock.get()), kNumThreads); | 315 new ForwardingProxyResolverFactory(mock.get()), kNumThreads); |
322 | 316 |
323 int rv; | 317 int rv; |
324 | 318 |
325 // Initialize the resolver. | 319 // Initialize the resolver. |
326 TestCompletionCallback init_callback; | 320 TestCompletionCallback init_callback; |
327 rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("foo"), | 321 rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("foo"), |
328 init_callback.callback()); | 322 init_callback.callback()); |
329 EXPECT_EQ(OK, init_callback.WaitForResult()); | 323 EXPECT_EQ(OK, init_callback.WaitForResult()); |
330 | 324 |
331 // Block the proxy resolver, so no request can complete. | 325 // Block the proxy resolver, so no request can complete. |
332 mock->Block(); | 326 mock->Block(); |
333 | 327 |
334 // Start request 0. | 328 // Start request 0. |
335 ProxyResolver::RequestHandle request0; | 329 ProxyResolver::RequestHandle request0; |
336 TestCompletionCallback callback0; | 330 TestCompletionCallback callback0; |
337 ProxyInfo results0; | 331 ProxyInfo results0; |
338 CapturingBoundNetLog log0; | 332 CapturingBoundNetLog log0; |
339 rv = resolver.GetProxyForURL(GURL("http://request0"), &results0, | 333 rv = resolver.GetProxyForURL(GURL("http://request0"), |
340 callback0.callback(), &request0, log0.bound()); | 334 &results0, |
| 335 callback0.callback(), |
| 336 &request0, |
| 337 log0.bound()); |
341 EXPECT_EQ(ERR_IO_PENDING, rv); | 338 EXPECT_EQ(ERR_IO_PENDING, rv); |
342 | 339 |
343 // Start 2 more requests (request1 and request2). | 340 // Start 2 more requests (request1 and request2). |
344 | 341 |
345 TestCompletionCallback callback1; | 342 TestCompletionCallback callback1; |
346 ProxyInfo results1; | 343 ProxyInfo results1; |
347 CapturingBoundNetLog log1; | 344 CapturingBoundNetLog log1; |
348 rv = resolver.GetProxyForURL(GURL("http://request1"), &results1, | 345 rv = resolver.GetProxyForURL(GURL("http://request1"), |
349 callback1.callback(), NULL, log1.bound()); | 346 &results1, |
| 347 callback1.callback(), |
| 348 NULL, |
| 349 log1.bound()); |
350 EXPECT_EQ(ERR_IO_PENDING, rv); | 350 EXPECT_EQ(ERR_IO_PENDING, rv); |
351 | 351 |
352 ProxyResolver::RequestHandle request2; | 352 ProxyResolver::RequestHandle request2; |
353 TestCompletionCallback callback2; | 353 TestCompletionCallback callback2; |
354 ProxyInfo results2; | 354 ProxyInfo results2; |
355 CapturingBoundNetLog log2; | 355 CapturingBoundNetLog log2; |
356 rv = resolver.GetProxyForURL(GURL("http://request2"), &results2, | 356 rv = resolver.GetProxyForURL(GURL("http://request2"), |
357 callback2.callback(), &request2, log2.bound()); | 357 &results2, |
| 358 callback2.callback(), |
| 359 &request2, |
| 360 log2.bound()); |
358 EXPECT_EQ(ERR_IO_PENDING, rv); | 361 EXPECT_EQ(ERR_IO_PENDING, rv); |
359 | 362 |
360 // Unblock the worker thread so the requests can continue running. | 363 // Unblock the worker thread so the requests can continue running. |
361 mock->WaitUntilBlocked(); | 364 mock->WaitUntilBlocked(); |
362 mock->Unblock(); | 365 mock->Unblock(); |
363 | 366 |
364 // Check that request 0 completed as expected. | 367 // Check that request 0 completed as expected. |
365 // The NetLog has 1 entry that came from the MultiThreadedProxyResolver, and | 368 // The NetLog has 1 entry that came from the MultiThreadedProxyResolver, and |
366 // 1 entry from the mock proxy resolver. | 369 // 1 entry from the mock proxy resolver. |
367 EXPECT_EQ(0, callback0.WaitForResult()); | 370 EXPECT_EQ(0, callback0.WaitForResult()); |
368 EXPECT_EQ("PROXY request0:80", results0.ToPacString()); | 371 EXPECT_EQ("PROXY request0:80", results0.ToPacString()); |
369 | 372 |
370 CapturingNetLog::CapturedEntryList entries0; | 373 CapturingNetLog::CapturedEntryList entries0; |
371 log0.GetEntries(&entries0); | 374 log0.GetEntries(&entries0); |
372 | 375 |
373 ASSERT_EQ(2u, entries0.size()); | 376 ASSERT_EQ(2u, entries0.size()); |
374 EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, | 377 EXPECT_EQ(NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, entries0[0].type); |
375 entries0[0].type); | |
376 | 378 |
377 // Check that request 1 completed as expected. | 379 // Check that request 1 completed as expected. |
378 EXPECT_EQ(1, callback1.WaitForResult()); | 380 EXPECT_EQ(1, callback1.WaitForResult()); |
379 EXPECT_EQ("PROXY request1:80", results1.ToPacString()); | 381 EXPECT_EQ("PROXY request1:80", results1.ToPacString()); |
380 | 382 |
381 CapturingNetLog::CapturedEntryList entries1; | 383 CapturingNetLog::CapturedEntryList entries1; |
382 log1.GetEntries(&entries1); | 384 log1.GetEntries(&entries1); |
383 | 385 |
384 ASSERT_EQ(4u, entries1.size()); | 386 ASSERT_EQ(4u, entries1.size()); |
385 EXPECT_TRUE(LogContainsBeginEvent( | 387 EXPECT_TRUE(LogContainsBeginEvent( |
386 entries1, 0, | 388 entries1, 0, NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); |
387 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); | |
388 EXPECT_TRUE(LogContainsEndEvent( | 389 EXPECT_TRUE(LogContainsEndEvent( |
389 entries1, 1, | 390 entries1, 1, NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); |
390 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); | |
391 | 391 |
392 // Check that request 2 completed as expected. | 392 // Check that request 2 completed as expected. |
393 EXPECT_EQ(2, callback2.WaitForResult()); | 393 EXPECT_EQ(2, callback2.WaitForResult()); |
394 EXPECT_EQ("PROXY request2:80", results2.ToPacString()); | 394 EXPECT_EQ("PROXY request2:80", results2.ToPacString()); |
395 | 395 |
396 CapturingNetLog::CapturedEntryList entries2; | 396 CapturingNetLog::CapturedEntryList entries2; |
397 log2.GetEntries(&entries2); | 397 log2.GetEntries(&entries2); |
398 | 398 |
399 ASSERT_EQ(4u, entries2.size()); | 399 ASSERT_EQ(4u, entries2.size()); |
400 EXPECT_TRUE(LogContainsBeginEvent( | 400 EXPECT_TRUE(LogContainsBeginEvent( |
401 entries2, 0, | 401 entries2, 0, NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); |
402 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); | |
403 EXPECT_TRUE(LogContainsEndEvent( | 402 EXPECT_TRUE(LogContainsEndEvent( |
404 entries2, 1, | 403 entries2, 1, NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); |
405 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD)); | |
406 } | 404 } |
407 | 405 |
408 // Cancel a request which is in progress, and then cancel a request which | 406 // Cancel a request which is in progress, and then cancel a request which |
409 // is pending. | 407 // is pending. |
410 TEST(MultiThreadedProxyResolverTest, SingleThread_CancelRequest) { | 408 TEST(MultiThreadedProxyResolverTest, SingleThread_CancelRequest) { |
411 const size_t kNumThreads = 1u; | 409 const size_t kNumThreads = 1u; |
412 scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver); | 410 scoped_ptr<BlockableProxyResolver> mock(new BlockableProxyResolver); |
413 MultiThreadedProxyResolver resolver( | 411 MultiThreadedProxyResolver resolver( |
414 new ForwardingProxyResolverFactory(mock.get()), | 412 new ForwardingProxyResolverFactory(mock.get()), kNumThreads); |
415 kNumThreads); | |
416 | 413 |
417 int rv; | 414 int rv; |
418 | 415 |
419 // Initialize the resolver. | 416 // Initialize the resolver. |
420 TestCompletionCallback init_callback; | 417 TestCompletionCallback init_callback; |
421 rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("foo"), | 418 rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("foo"), |
422 init_callback.callback()); | 419 init_callback.callback()); |
423 EXPECT_EQ(OK, init_callback.WaitForResult()); | 420 EXPECT_EQ(OK, init_callback.WaitForResult()); |
424 | 421 |
425 // Block the proxy resolver, so no request can complete. | 422 // Block the proxy resolver, so no request can complete. |
426 mock->Block(); | 423 mock->Block(); |
427 | 424 |
428 // Start request 0. | 425 // Start request 0. |
429 ProxyResolver::RequestHandle request0; | 426 ProxyResolver::RequestHandle request0; |
430 TestCompletionCallback callback0; | 427 TestCompletionCallback callback0; |
431 ProxyInfo results0; | 428 ProxyInfo results0; |
432 rv = resolver.GetProxyForURL(GURL("http://request0"), &results0, | 429 rv = resolver.GetProxyForURL(GURL("http://request0"), |
433 callback0.callback(), &request0, BoundNetLog()); | 430 &results0, |
| 431 callback0.callback(), |
| 432 &request0, |
| 433 BoundNetLog()); |
434 EXPECT_EQ(ERR_IO_PENDING, rv); | 434 EXPECT_EQ(ERR_IO_PENDING, rv); |
435 | 435 |
436 // Wait until requests 0 reaches the worker thread. | 436 // Wait until requests 0 reaches the worker thread. |
437 mock->WaitUntilBlocked(); | 437 mock->WaitUntilBlocked(); |
438 | 438 |
439 // Start 3 more requests (request1 : request3). | 439 // Start 3 more requests (request1 : request3). |
440 | 440 |
441 TestCompletionCallback callback1; | 441 TestCompletionCallback callback1; |
442 ProxyInfo results1; | 442 ProxyInfo results1; |
443 rv = resolver.GetProxyForURL(GURL("http://request1"), &results1, | 443 rv = resolver.GetProxyForURL(GURL("http://request1"), |
444 callback1.callback(), NULL, BoundNetLog()); | 444 &results1, |
| 445 callback1.callback(), |
| 446 NULL, |
| 447 BoundNetLog()); |
445 EXPECT_EQ(ERR_IO_PENDING, rv); | 448 EXPECT_EQ(ERR_IO_PENDING, rv); |
446 | 449 |
447 ProxyResolver::RequestHandle request2; | 450 ProxyResolver::RequestHandle request2; |
448 TestCompletionCallback callback2; | 451 TestCompletionCallback callback2; |
449 ProxyInfo results2; | 452 ProxyInfo results2; |
450 rv = resolver.GetProxyForURL(GURL("http://request2"), &results2, | 453 rv = resolver.GetProxyForURL(GURL("http://request2"), |
451 callback2.callback(), &request2, BoundNetLog()); | 454 &results2, |
| 455 callback2.callback(), |
| 456 &request2, |
| 457 BoundNetLog()); |
452 EXPECT_EQ(ERR_IO_PENDING, rv); | 458 EXPECT_EQ(ERR_IO_PENDING, rv); |
453 | 459 |
454 TestCompletionCallback callback3; | 460 TestCompletionCallback callback3; |
455 ProxyInfo results3; | 461 ProxyInfo results3; |
456 rv = resolver.GetProxyForURL(GURL("http://request3"), &results3, | 462 rv = resolver.GetProxyForURL(GURL("http://request3"), |
457 callback3.callback(), NULL, BoundNetLog()); | 463 &results3, |
| 464 callback3.callback(), |
| 465 NULL, |
| 466 BoundNetLog()); |
458 EXPECT_EQ(ERR_IO_PENDING, rv); | 467 EXPECT_EQ(ERR_IO_PENDING, rv); |
459 | 468 |
460 // Cancel request0 (inprogress) and request2 (pending). | 469 // Cancel request0 (inprogress) and request2 (pending). |
461 resolver.CancelRequest(request0); | 470 resolver.CancelRequest(request0); |
462 resolver.CancelRequest(request2); | 471 resolver.CancelRequest(request2); |
463 | 472 |
464 // Unblock the worker thread so the requests can continue running. | 473 // Unblock the worker thread so the requests can continue running. |
465 mock->Unblock(); | 474 mock->Unblock(); |
466 | 475 |
467 // Wait for requests 1 and 3 to finish. | 476 // Wait for requests 1 and 3 to finish. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 init_callback.callback()); | 508 init_callback.callback()); |
500 EXPECT_EQ(OK, init_callback.WaitForResult()); | 509 EXPECT_EQ(OK, init_callback.WaitForResult()); |
501 | 510 |
502 // Block the proxy resolver, so no request can complete. | 511 // Block the proxy resolver, so no request can complete. |
503 mock->Block(); | 512 mock->Block(); |
504 | 513 |
505 // Start 3 requests. | 514 // Start 3 requests. |
506 | 515 |
507 TestCompletionCallback callback0; | 516 TestCompletionCallback callback0; |
508 ProxyInfo results0; | 517 ProxyInfo results0; |
509 rv = resolver->GetProxyForURL(GURL("http://request0"), &results0, | 518 rv = resolver->GetProxyForURL(GURL("http://request0"), |
510 callback0.callback(), NULL, BoundNetLog()); | 519 &results0, |
| 520 callback0.callback(), |
| 521 NULL, |
| 522 BoundNetLog()); |
511 EXPECT_EQ(ERR_IO_PENDING, rv); | 523 EXPECT_EQ(ERR_IO_PENDING, rv); |
512 | 524 |
513 TestCompletionCallback callback1; | 525 TestCompletionCallback callback1; |
514 ProxyInfo results1; | 526 ProxyInfo results1; |
515 rv = resolver->GetProxyForURL(GURL("http://request1"), &results1, | 527 rv = resolver->GetProxyForURL(GURL("http://request1"), |
516 callback1.callback(), NULL, BoundNetLog()); | 528 &results1, |
| 529 callback1.callback(), |
| 530 NULL, |
| 531 BoundNetLog()); |
517 EXPECT_EQ(ERR_IO_PENDING, rv); | 532 EXPECT_EQ(ERR_IO_PENDING, rv); |
518 | 533 |
519 TestCompletionCallback callback2; | 534 TestCompletionCallback callback2; |
520 ProxyInfo results2; | 535 ProxyInfo results2; |
521 rv = resolver->GetProxyForURL(GURL("http://request2"), &results2, | 536 rv = resolver->GetProxyForURL(GURL("http://request2"), |
522 callback2.callback(), NULL, BoundNetLog()); | 537 &results2, |
| 538 callback2.callback(), |
| 539 NULL, |
| 540 BoundNetLog()); |
523 EXPECT_EQ(ERR_IO_PENDING, rv); | 541 EXPECT_EQ(ERR_IO_PENDING, rv); |
524 | 542 |
525 // Wait until request 0 reaches the worker thread. | 543 // Wait until request 0 reaches the worker thread. |
526 mock->WaitUntilBlocked(); | 544 mock->WaitUntilBlocked(); |
527 | 545 |
528 // Add some latency, to improve the chance that when | 546 // Add some latency, to improve the chance that when |
529 // MultiThreadedProxyResolver is deleted below we are still running inside | 547 // MultiThreadedProxyResolver is deleted below we are still running inside |
530 // of the worker thread. The test will pass regardless, so this race doesn't | 548 // of the worker thread. The test will pass regardless, so this race doesn't |
531 // cause flakiness. However the destruction during execution is a more | 549 // cause flakiness. However the destruction during execution is a more |
532 // interesting case to test. | 550 // interesting case to test. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 EXPECT_EQ(ASCIIToUTF16("pac script bytes"), | 621 EXPECT_EQ(ASCIIToUTF16("pac script bytes"), |
604 factory->resolvers()[0]->last_script_data()->utf16()); | 622 factory->resolvers()[0]->last_script_data()->utf16()); |
605 | 623 |
606 const int kNumRequests = 9; | 624 const int kNumRequests = 9; |
607 TestCompletionCallback callback[kNumRequests]; | 625 TestCompletionCallback callback[kNumRequests]; |
608 ProxyInfo results[kNumRequests]; | 626 ProxyInfo results[kNumRequests]; |
609 ProxyResolver::RequestHandle request[kNumRequests]; | 627 ProxyResolver::RequestHandle request[kNumRequests]; |
610 | 628 |
611 // Start request 0 -- this should run on thread 0 as there is nothing else | 629 // Start request 0 -- this should run on thread 0 as there is nothing else |
612 // going on right now. | 630 // going on right now. |
613 rv = resolver.GetProxyForURL( | 631 rv = resolver.GetProxyForURL(GURL("http://request0"), |
614 GURL("http://request0"), &results[0], callback[0].callback(), &request[0], | 632 &results[0], |
615 BoundNetLog()); | 633 callback[0].callback(), |
| 634 &request[0], |
| 635 BoundNetLog()); |
616 EXPECT_EQ(ERR_IO_PENDING, rv); | 636 EXPECT_EQ(ERR_IO_PENDING, rv); |
617 | 637 |
618 // Wait for request 0 to finish. | 638 // Wait for request 0 to finish. |
619 rv = callback[0].WaitForResult(); | 639 rv = callback[0].WaitForResult(); |
620 EXPECT_EQ(0, rv); | 640 EXPECT_EQ(0, rv); |
621 EXPECT_EQ("PROXY request0:80", results[0].ToPacString()); | 641 EXPECT_EQ("PROXY request0:80", results[0].ToPacString()); |
622 ASSERT_EQ(1u, factory->resolvers().size()); | 642 ASSERT_EQ(1u, factory->resolvers().size()); |
623 EXPECT_EQ(1, factory->resolvers()[0]->request_count()); | 643 EXPECT_EQ(1, factory->resolvers()[0]->request_count()); |
624 | 644 |
625 base::MessageLoop::current()->RunUntilIdle(); | 645 base::MessageLoop::current()->RunUntilIdle(); |
626 | 646 |
627 // We now start 8 requests in parallel -- this will cause the maximum of | 647 // We now start 8 requests in parallel -- this will cause the maximum of |
628 // three threads to be provisioned (an additional two from what we already | 648 // three threads to be provisioned (an additional two from what we already |
629 // have). | 649 // have). |
630 | 650 |
631 for (int i = 1; i < kNumRequests; ++i) { | 651 for (int i = 1; i < kNumRequests; ++i) { |
632 rv = resolver.GetProxyForURL( | 652 rv = |
633 GURL(base::StringPrintf("http://request%d", i)), &results[i], | 653 resolver.GetProxyForURL(GURL(base::StringPrintf("http://request%d", i)), |
634 callback[i].callback(), &request[i], BoundNetLog()); | 654 &results[i], |
| 655 callback[i].callback(), |
| 656 &request[i], |
| 657 BoundNetLog()); |
635 EXPECT_EQ(ERR_IO_PENDING, rv); | 658 EXPECT_EQ(ERR_IO_PENDING, rv); |
636 } | 659 } |
637 | 660 |
638 // We should now have a total of 3 threads, each with its own ProxyResolver | 661 // We should now have a total of 3 threads, each with its own ProxyResolver |
639 // that will get initialized with the same data. (We check this later since | 662 // that will get initialized with the same data. (We check this later since |
640 // the assignment happens on the worker threads and may not have occurred | 663 // the assignment happens on the worker threads and may not have occurred |
641 // yet.) | 664 // yet.) |
642 ASSERT_EQ(3u, factory->resolvers().size()); | 665 ASSERT_EQ(3u, factory->resolvers().size()); |
643 | 666 |
644 // Cancel 3 of the 8 oustanding requests. | 667 // Cancel 3 of the 8 oustanding requests. |
(...skipping 17 matching lines...) Expand all Loading... |
662 // (That way we can test to see the values observed by the synchronous | 685 // (That way we can test to see the values observed by the synchronous |
663 // resolvers in a non-racy manner). | 686 // resolvers in a non-racy manner). |
664 TestCompletionCallback set_script_callback2; | 687 TestCompletionCallback set_script_callback2; |
665 rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("xyz"), | 688 rv = resolver.SetPacScript(ProxyResolverScriptData::FromUTF8("xyz"), |
666 set_script_callback2.callback()); | 689 set_script_callback2.callback()); |
667 EXPECT_EQ(ERR_IO_PENDING, rv); | 690 EXPECT_EQ(ERR_IO_PENDING, rv); |
668 EXPECT_EQ(OK, set_script_callback2.WaitForResult()); | 691 EXPECT_EQ(OK, set_script_callback2.WaitForResult()); |
669 ASSERT_EQ(4u, factory->resolvers().size()); | 692 ASSERT_EQ(4u, factory->resolvers().size()); |
670 | 693 |
671 for (int i = 0; i < 3; ++i) { | 694 for (int i = 0; i < 3; ++i) { |
672 EXPECT_EQ( | 695 EXPECT_EQ(ASCIIToUTF16("pac script bytes"), |
673 ASCIIToUTF16("pac script bytes"), | 696 factory->resolvers()[i]->last_script_data()->utf16()) |
674 factory->resolvers()[i]->last_script_data()->utf16()) << "i=" << i; | 697 << "i=" << i; |
675 } | 698 } |
676 | 699 |
677 EXPECT_EQ(ASCIIToUTF16("xyz"), | 700 EXPECT_EQ(ASCIIToUTF16("xyz"), |
678 factory->resolvers()[3]->last_script_data()->utf16()); | 701 factory->resolvers()[3]->last_script_data()->utf16()); |
679 | 702 |
680 // We don't know the exact ordering that requests ran on threads with, | 703 // We don't know the exact ordering that requests ran on threads with, |
681 // but we do know the total count that should have reached the threads. | 704 // but we do know the total count that should have reached the threads. |
682 // 8 total were submitted, and three were cancelled. Of the three that | 705 // 8 total were submitted, and three were cancelled. Of the three that |
683 // were cancelled, one of them (request 1) was cancelled after it had | 706 // were cancelled, one of them (request 1) was cancelled after it had |
684 // already been posted to the worker thread. So the resolvers will | 707 // already been posted to the worker thread. So the resolvers will |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 | 740 |
718 const int kNumRequests = 4; | 741 const int kNumRequests = 4; |
719 TestCompletionCallback callback[kNumRequests]; | 742 TestCompletionCallback callback[kNumRequests]; |
720 ProxyInfo results[kNumRequests]; | 743 ProxyInfo results[kNumRequests]; |
721 ProxyResolver::RequestHandle request[kNumRequests]; | 744 ProxyResolver::RequestHandle request[kNumRequests]; |
722 | 745 |
723 // Start a request that will block the first thread. | 746 // Start a request that will block the first thread. |
724 | 747 |
725 factory->resolvers()[0]->Block(); | 748 factory->resolvers()[0]->Block(); |
726 | 749 |
727 rv = resolver.GetProxyForURL( | 750 rv = resolver.GetProxyForURL(GURL("http://request0"), |
728 GURL("http://request0"), &results[0], callback[0].callback(), &request[0], | 751 &results[0], |
729 BoundNetLog()); | 752 callback[0].callback(), |
| 753 &request[0], |
| 754 BoundNetLog()); |
730 | 755 |
731 EXPECT_EQ(ERR_IO_PENDING, rv); | 756 EXPECT_EQ(ERR_IO_PENDING, rv); |
732 factory->resolvers()[0]->WaitUntilBlocked(); | 757 factory->resolvers()[0]->WaitUntilBlocked(); |
733 | 758 |
734 // Start 3 more requests -- they should all be serviced by thread #2 | 759 // Start 3 more requests -- they should all be serviced by thread #2 |
735 // since thread #1 is blocked. | 760 // since thread #1 is blocked. |
736 | 761 |
737 for (int i = 1; i < kNumRequests; ++i) { | 762 for (int i = 1; i < kNumRequests; ++i) { |
738 rv = resolver.GetProxyForURL( | 763 rv = |
739 GURL(base::StringPrintf("http://request%d", i)), | 764 resolver.GetProxyForURL(GURL(base::StringPrintf("http://request%d", i)), |
740 &results[i], callback[i].callback(), &request[i], BoundNetLog()); | 765 &results[i], |
| 766 callback[i].callback(), |
| 767 &request[i], |
| 768 BoundNetLog()); |
741 EXPECT_EQ(ERR_IO_PENDING, rv); | 769 EXPECT_EQ(ERR_IO_PENDING, rv); |
742 } | 770 } |
743 | 771 |
744 // Wait for the three requests to complete (they should complete in FIFO | 772 // Wait for the three requests to complete (they should complete in FIFO |
745 // order). | 773 // order). |
746 for (int i = 1; i < kNumRequests; ++i) { | 774 for (int i = 1; i < kNumRequests; ++i) { |
747 EXPECT_EQ(i - 1, callback[i].WaitForResult()); | 775 EXPECT_EQ(i - 1, callback[i].WaitForResult()); |
748 } | 776 } |
749 | 777 |
750 // Unblock the first thread. | 778 // Unblock the first thread. |
751 factory->resolvers()[0]->Unblock(); | 779 factory->resolvers()[0]->Unblock(); |
752 EXPECT_EQ(0, callback[0].WaitForResult()); | 780 EXPECT_EQ(0, callback[0].WaitForResult()); |
753 | 781 |
754 // All in all, the first thread should have seen just 1 request. And the | 782 // All in all, the first thread should have seen just 1 request. And the |
755 // second thread 3 requests. | 783 // second thread 3 requests. |
756 ASSERT_EQ(2u, factory->resolvers().size()); | 784 ASSERT_EQ(2u, factory->resolvers().size()); |
757 EXPECT_EQ(1, factory->resolvers()[0]->request_count()); | 785 EXPECT_EQ(1, factory->resolvers()[0]->request_count()); |
758 EXPECT_EQ(3, factory->resolvers()[1]->request_count()); | 786 EXPECT_EQ(3, factory->resolvers()[1]->request_count()); |
759 } | 787 } |
760 | 788 |
761 } // namespace | 789 } // namespace |
762 | 790 |
763 } // namespace net | 791 } // namespace net |
OLD | NEW |