OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "base/compiler_specific.h" | 5 #include <vector> |
| 6 |
| 7 #include "base/logging.h" |
6 #include "googleurl/src/gurl.h" | 8 #include "googleurl/src/gurl.h" |
7 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
| 10 #include "net/base/test_completion_callback.h" |
8 #include "net/proxy/proxy_config_service.h" | 11 #include "net/proxy/proxy_config_service.h" |
9 #include "net/proxy/proxy_resolver.h" | 12 #include "net/proxy/proxy_resolver.h" |
10 #include "net/proxy/proxy_script_fetcher.h" | 13 #include "net/proxy/proxy_script_fetcher.h" |
11 #include "net/proxy/proxy_service.h" | 14 #include "net/proxy/proxy_service.h" |
12 #include "net/proxy/single_threaded_proxy_resolver.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
14 | 16 |
15 namespace { | 17 namespace { |
16 | 18 |
17 class MockProxyConfigService: public net::ProxyConfigService { | 19 class MockProxyConfigService: public net::ProxyConfigService { |
18 public: | 20 public: |
19 MockProxyConfigService() {} // Direct connect. | 21 MockProxyConfigService() {} // Direct connect. |
20 explicit MockProxyConfigService(const net::ProxyConfig& pc) : config(pc) {} | 22 explicit MockProxyConfigService(const net::ProxyConfig& pc) : config(pc) {} |
21 explicit MockProxyConfigService(const std::string& pac_url) { | 23 explicit MockProxyConfigService(const std::string& pac_url) { |
22 config.pac_url = GURL(pac_url); | 24 config.pac_url = GURL(pac_url); |
23 } | 25 } |
24 | 26 |
25 virtual int GetProxyConfig(net::ProxyConfig* results) { | 27 virtual int GetProxyConfig(net::ProxyConfig* results) { |
26 *results = config; | 28 *results = config; |
27 return net::OK; | 29 return net::OK; |
28 } | 30 } |
29 | 31 |
30 net::ProxyConfig config; | 32 net::ProxyConfig config; |
31 }; | 33 }; |
32 | 34 |
33 class SyncMockProxyResolver : public net::ProxyResolver { | 35 // Asynchronous mock proxy resolver. All requests complete asynchronously, |
| 36 // user must call Request::CompleteNow() on a pending request to signal it. |
| 37 class MockAsyncProxyResolverBase : public net::ProxyResolver { |
34 public: | 38 public: |
35 SyncMockProxyResolver() : net::ProxyResolver(false /*expects_pac_bytes*/), | 39 class Request : public base::RefCounted<Request> { |
36 fail_get_proxy_for_url(false) { | 40 public: |
| 41 Request(MockAsyncProxyResolverBase* resolver, |
| 42 const GURL& url, |
| 43 net::ProxyInfo* results, |
| 44 net::CompletionCallback* callback) |
| 45 : resolver_(resolver), |
| 46 url_(url), |
| 47 results_(results), |
| 48 callback_(callback), |
| 49 origin_loop_(MessageLoop::current()) { |
| 50 } |
| 51 |
| 52 const GURL& url() const { return url_; } |
| 53 net::ProxyInfo* results() const { return results_; } |
| 54 net::CompletionCallback* callback() const { return callback_; } |
| 55 |
| 56 void CompleteNow(int rv) { |
| 57 net::CompletionCallback* callback = callback_; |
| 58 |
| 59 // May delete |this|. |
| 60 resolver_->RemovePendingRequest(this); |
| 61 |
| 62 callback->Run(rv); |
| 63 } |
| 64 |
| 65 private: |
| 66 MockAsyncProxyResolverBase* resolver_; |
| 67 const GURL url_; |
| 68 net::ProxyInfo* results_; |
| 69 net::CompletionCallback* callback_; |
| 70 MessageLoop* origin_loop_; |
| 71 }; |
| 72 |
| 73 typedef std::vector<scoped_refptr<Request> > RequestsList; |
| 74 |
| 75 // ProxyResolver implementation: |
| 76 virtual int GetProxyForURL(const GURL& url, |
| 77 net::ProxyInfo* results, |
| 78 net::CompletionCallback* callback, |
| 79 RequestHandle* request_handle) { |
| 80 scoped_refptr<Request> request = new Request(this, url, results, callback); |
| 81 pending_requests_.push_back(request); |
| 82 |
| 83 if (request_handle) |
| 84 *request_handle = reinterpret_cast<RequestHandle>(request.get()); |
| 85 |
| 86 // Test code completes the request by calling request->CompleteNow(). |
| 87 return net::ERR_IO_PENDING; |
37 } | 88 } |
38 | 89 |
39 // ProxyResolver implementation: | 90 virtual void CancelRequest(RequestHandle request_handle) { |
40 virtual int GetProxyForURL(const GURL& query_url, | 91 scoped_refptr<Request> request = reinterpret_cast<Request*>(request_handle); |
41 net::ProxyInfo* results, | 92 cancelled_requests_.push_back(request); |
42 net::CompletionCallback* callback, | 93 RemovePendingRequest(request); |
43 RequestHandle* request) { | |
44 if (fail_get_proxy_for_url) | |
45 return net::ERR_FAILED; | |
46 if (GURL(query_url).host() == info_predicate_query_host) { | |
47 results->Use(info); | |
48 } else { | |
49 results->UseDirect(); | |
50 } | |
51 return net::OK; | |
52 } | 94 } |
53 | 95 |
54 virtual void CancelRequest(RequestHandle request) { | 96 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) { |
55 NOTREACHED(); | 97 pac_url_ = pac_url; |
56 } | |
57 | |
58 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {} | |
59 | |
60 | |
61 net::ProxyInfo info; | |
62 | |
63 // info is only returned if query_url in GetProxyForURL matches this: | |
64 std::string info_predicate_query_host; | |
65 | |
66 // If true, then GetProxyForURL will fail, which simulates failure to | |
67 // download or execute the PAC file. | |
68 bool fail_get_proxy_for_url; | |
69 }; | |
70 | |
71 class MockProxyResolver : public net::SingleThreadedProxyResolver { | |
72 public: | |
73 MockProxyResolver() | |
74 : net::SingleThreadedProxyResolver(new SyncMockProxyResolver) { | |
75 x = reinterpret_cast<SyncMockProxyResolver*>(resolver()); | |
76 } | |
77 | |
78 // TODO(eroman): cleanup. | |
79 SyncMockProxyResolver* x; | |
80 }; | |
81 | |
82 // ResultFuture is a handle to get at the result from | |
83 // ProxyService::ResolveProxyForURL() that ran on another thread. | |
84 class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> { | |
85 public: | |
86 // |service| is the ProxyService to issue requests on, and |io_message_loop| | |
87 // is the message loop where ProxyService lives. | |
88 ResultFuture(MessageLoop* io_message_loop, | |
89 net::ProxyService* service) | |
90 : io_message_loop_(io_message_loop), | |
91 service_(service), | |
92 request_(NULL), | |
93 ALLOW_THIS_IN_INITIALIZER_LIST( | |
94 callback_(this, &ResultFuture::OnCompletion)), | |
95 completion_(true, false), | |
96 cancelled_(false, false), | |
97 started_(false, false), | |
98 did_complete_(false) { | |
99 } | |
100 | |
101 // Block until the request has completed, then return the result. | |
102 int GetResultCode() { | |
103 DCHECK(MessageLoop::current() != io_message_loop_); | |
104 WaitUntilCompleted(); | |
105 return result_code_; | |
106 } | |
107 | |
108 // Block until the request has completed, then return the result. | |
109 const net::ProxyInfo& GetProxyInfo() { | |
110 DCHECK(MessageLoop::current() != io_message_loop_); | |
111 WaitUntilCompleted(); | |
112 return proxy_info_; | |
113 } | |
114 | |
115 // Cancel this request (wait until the cancel has been issued before | |
116 // returning). | |
117 void Cancel() { | |
118 DCHECK(MessageLoop::current() != io_message_loop_); | |
119 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
120 this, &ResultFuture::DoCancel)); | |
121 cancelled_.Wait(); | |
122 } | |
123 | |
124 // Return true if the request has already completed. | |
125 bool IsCompleted() { | |
126 DCHECK(MessageLoop::current() != io_message_loop_); | |
127 return did_complete_; | |
128 } | |
129 | |
130 // Wait until the ProxyService completes this request. | |
131 void WaitUntilCompleted() { | |
132 DCHECK(MessageLoop::current() != io_message_loop_); | |
133 completion_.Wait(); | |
134 DCHECK(did_complete_); | |
135 } | |
136 | |
137 private: | |
138 friend class ProxyServiceWithFutures; | |
139 | |
140 typedef int (net::ProxyService::*RequestMethod)(const GURL&, net::ProxyInfo*, | |
141 net::CompletionCallback*, net::ProxyService::PacRequest**); | |
142 | |
143 void StartResolve(const GURL& url) { | |
144 StartRequest(url, &net::ProxyService::ResolveProxy); | |
145 } | |
146 | |
147 // |proxy_info| is the *previous* result (that we are reconsidering). | |
148 void StartReconsider(const GURL& url, const net::ProxyInfo& proxy_info) { | |
149 proxy_info_ = proxy_info; | |
150 StartRequest(url, &net::ProxyService::ReconsiderProxyAfterError); | |
151 } | |
152 | |
153 // Start the request. Return once ProxyService::GetProxyForURL() or | |
154 // ProxyService::ReconsiderProxyAfterError() returns. | |
155 void StartRequest(const GURL& url, RequestMethod method) { | |
156 DCHECK(MessageLoop::current() != io_message_loop_); | |
157 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
158 this, &ResultFuture::DoStartRequest, url, method)); | |
159 started_.Wait(); | |
160 } | |
161 | |
162 void StartResetConfigService( | |
163 net::ProxyConfigService* new_proxy_config_service) { | |
164 DCHECK(MessageLoop::current() != io_message_loop_); | |
165 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
166 this, &ResultFuture::DoResetConfigService, new_proxy_config_service)); | |
167 started_.Wait(); | |
168 } | |
169 | |
170 // Called on |io_message_loop_|. | |
171 void DoStartRequest(const GURL& url, RequestMethod method) { | |
172 DCHECK(MessageLoop::current() == io_message_loop_); | |
173 int rv = (service_->*method)(url, &proxy_info_, &callback_, &request_); | |
174 if (rv != net::ERR_IO_PENDING) { | |
175 // Completed synchronously. | |
176 OnCompletion(rv); | |
177 } | |
178 started_.Signal(); | |
179 } | |
180 | |
181 // Called on |io_message_loop_|. | |
182 void DoResetConfigService(net::ProxyConfigService* new_proxy_config_service) { | |
183 DCHECK(MessageLoop::current() == io_message_loop_); | |
184 service_->ResetConfigService(new_proxy_config_service); | |
185 started_.Signal(); | |
186 OnCompletion(0); | |
187 } | |
188 | |
189 // Called on |io_message_loop_|. | |
190 void DoCancel() { | |
191 DCHECK(MessageLoop::current() == io_message_loop_); | |
192 if (!did_complete_) | |
193 service_->CancelPacRequest(request_); | |
194 cancelled_.Signal(); | |
195 } | |
196 | |
197 // Called on |io_message_loop_|. | |
198 void OnCompletion(int result) { | |
199 DCHECK(MessageLoop::current() == io_message_loop_); | |
200 DCHECK(!did_complete_); | |
201 did_complete_ = true; | |
202 result_code_ = result; | |
203 request_ = NULL; | |
204 completion_.Signal(); | |
205 } | |
206 | |
207 // The message loop where the ProxyService lives. | |
208 MessageLoop* io_message_loop_; | |
209 | |
210 // The proxy service that started this request. | |
211 net::ProxyService* service_; | |
212 | |
213 // The in-progress request. | |
214 net::ProxyService::PacRequest* request_; | |
215 | |
216 net::CompletionCallbackImpl<ResultFuture> callback_; | |
217 base::WaitableEvent completion_; | |
218 base::WaitableEvent cancelled_; | |
219 base::WaitableEvent started_; | |
220 bool did_complete_; | |
221 | |
222 // Results from the request. | |
223 int result_code_; | |
224 net::ProxyInfo proxy_info_; | |
225 }; | |
226 | |
227 // Wraps a ProxyService running on its own IO thread. | |
228 class ProxyServiceWithFutures { | |
229 public: | |
230 ProxyServiceWithFutures(net::ProxyConfigService* config_service, | |
231 net::ProxyResolver* resolver) | |
232 : io_thread_("IO_Thread"), | |
233 io_thread_state_(new IOThreadState) { | |
234 base::Thread::Options options; | |
235 options.message_loop_type = MessageLoop::TYPE_IO; | |
236 io_thread_.StartWithOptions(options); | |
237 | |
238 // Initialize state that lives on |io_thread_|. | |
239 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
240 io_thread_state_.get(), &IOThreadState::DoInit, | |
241 config_service, resolver)); | |
242 io_thread_state_->event.Wait(); | |
243 } | |
244 | |
245 ~ProxyServiceWithFutures() { | |
246 // Destroy state that lives on |io_thread_|. | |
247 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
248 io_thread_state_.get(), &IOThreadState::DoDestroy)); | |
249 io_thread_state_->event.Wait(); | |
250 } | |
251 | |
252 // Start the request on |io_thread_|, and return a handle that can be | |
253 // used to access the results. The caller is responsible for freeing | |
254 // the ResultFuture. | |
255 void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) { | |
256 *result = new ResultFuture(io_thread_.message_loop(), | |
257 io_thread_state_->service); | |
258 (*result)->StartResolve(url); | |
259 } | |
260 | |
261 // Same as above, but for "ReconsiderProxyAfterError()". | |
262 void ReconsiderProxyAfterError(scoped_refptr<ResultFuture>* result, | |
263 const GURL& url, | |
264 const net::ProxyInfo& proxy_info) { | |
265 *result = new ResultFuture(io_thread_.message_loop(), | |
266 io_thread_state_->service); | |
267 (*result)->StartReconsider(url, proxy_info); | |
268 } | |
269 | |
270 void ResetConfigService(scoped_refptr<ResultFuture>* result, | |
271 net::ProxyConfigService* new_proxy_config_service) { | |
272 *result = new ResultFuture(io_thread_.message_loop(), | |
273 io_thread_state_->service); | |
274 (*result)->StartResetConfigService(new_proxy_config_service); | |
275 } | |
276 | |
277 void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) { | |
278 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
279 io_thread_state_.get(), &IOThreadState::DoSetProxyScriptFetcher, | |
280 proxy_script_fetcher)); | |
281 io_thread_state_->event.Wait(); | |
282 } | |
283 | |
284 private: | |
285 // Class that encapsulates the state living on IO thread. It needs to be | |
286 // ref-counted for posting tasks. | |
287 class IOThreadState : public base::RefCountedThreadSafe<IOThreadState> { | |
288 public: | |
289 IOThreadState() : event(false, false), service(NULL) {} | |
290 | |
291 void DoInit(net::ProxyConfigService* config_service, | |
292 net::ProxyResolver* resolver) { | |
293 service = new net::ProxyService(config_service, resolver); | |
294 event.Signal(); | |
295 } | |
296 | |
297 void DoDestroy() { | |
298 delete service; | |
299 service = NULL; | |
300 event.Signal(); | |
301 } | |
302 | |
303 void DoSetProxyScriptFetcher( | |
304 net::ProxyScriptFetcher* proxy_script_fetcher) { | |
305 service->SetProxyScriptFetcher(proxy_script_fetcher); | |
306 event.Signal(); | |
307 } | |
308 | |
309 base::WaitableEvent event; | |
310 net::ProxyService* service; | |
311 }; | |
312 | |
313 base::Thread io_thread_; | |
314 scoped_refptr<IOThreadState> io_thread_state_; // Lives on |io_thread_|. | |
315 }; | |
316 | |
317 // Wrapper around ProxyServiceWithFutures to do one request at a time. | |
318 class SyncProxyService { | |
319 public: | |
320 SyncProxyService(net::ProxyConfigService* config_service, | |
321 net::ProxyResolver* resolver) | |
322 : service_(config_service, resolver) { | |
323 } | |
324 | |
325 int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) { | |
326 scoped_refptr<ResultFuture> result; | |
327 service_.ResolveProxy(&result, url); | |
328 *proxy_info = result->GetProxyInfo(); | |
329 return result->GetResultCode(); | |
330 } | |
331 | |
332 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) { | |
333 scoped_refptr<ResultFuture> result; | |
334 service_.ReconsiderProxyAfterError(&result, url, *proxy_info); | |
335 *proxy_info = result->GetProxyInfo(); | |
336 return result->GetResultCode(); | |
337 } | |
338 | |
339 int ResetConfigService(net::ProxyConfigService* new_proxy_config_service) { | |
340 scoped_refptr<ResultFuture> result; | |
341 service_.ResetConfigService(&result, new_proxy_config_service); | |
342 return result->GetResultCode(); | |
343 } | |
344 | |
345 private: | |
346 ProxyServiceWithFutures service_; | |
347 }; | |
348 | |
349 // A ProxyResolver which can be set to block upon reaching GetProxyForURL. | |
350 class SyncBlockableProxyResolver : public net::ProxyResolver { | |
351 public: | |
352 SyncBlockableProxyResolver() | |
353 : net::ProxyResolver(false /*expects_pac_bytes*/), | |
354 should_block_(false), | |
355 unblocked_(true, true), | |
356 blocked_(true, false) { | |
357 } | |
358 | |
359 void Block() { | |
360 should_block_ = true; | |
361 unblocked_.Reset(); | |
362 } | |
363 | |
364 void Unblock() { | |
365 should_block_ = false; | |
366 blocked_.Reset(); | |
367 unblocked_.Signal(); | |
368 } | |
369 | |
370 void WaitUntilBlocked() { | |
371 blocked_.Wait(); | |
372 } | |
373 | |
374 // net::ProxyResolver implementation: | |
375 virtual int GetProxyForURL(const GURL& query_url, | |
376 net::ProxyInfo* results, | |
377 net::CompletionCallback* callback, | |
378 RequestHandle* request) { | |
379 if (should_block_) { | |
380 blocked_.Signal(); | |
381 unblocked_.Wait(); | |
382 } | |
383 | |
384 results->UseNamedProxy(query_url.host()); | |
385 return net::OK; | |
386 } | |
387 | |
388 virtual void CancelRequest(RequestHandle request) { | |
389 NOTREACHED(); | |
390 } | |
391 | |
392 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {} | |
393 | |
394 private: | |
395 bool should_block_; | |
396 base::WaitableEvent unblocked_; | |
397 base::WaitableEvent blocked_; | |
398 }; | |
399 | |
400 class BlockableProxyResolver : public net::SingleThreadedProxyResolver { | |
401 public: | |
402 BlockableProxyResolver() | |
403 : net::SingleThreadedProxyResolver(new SyncBlockableProxyResolver) { | |
404 x = reinterpret_cast<SyncBlockableProxyResolver*>(resolver()); | |
405 } | |
406 | |
407 // TODO(eroman): cleanup. | |
408 SyncBlockableProxyResolver* x; | |
409 }; | |
410 | |
411 // A mock ProxyResolverWithoutFetch which concatenates the query's host with | |
412 // the last download PAC contents. This way the result describes what the last | |
413 // downloaded PAC script's contents were, in addition to the query url itself. | |
414 class SyncMockProxyResolverWithoutFetch : public net::ProxyResolver { | |
415 public: | |
416 SyncMockProxyResolverWithoutFetch() | |
417 : net::ProxyResolver(true /*expects_pac_bytes*/), | |
418 last_pac_contents_("NONE") {} | |
419 | |
420 // net::ProxyResolver implementation: | |
421 virtual int GetProxyForURL(const GURL& query_url, | |
422 net::ProxyInfo* results, | |
423 net::CompletionCallback* callback, | |
424 RequestHandle* request) { | |
425 results->UseNamedProxy(last_pac_contents_ + "." + query_url.host()); | |
426 return net::OK; | |
427 } | 98 } |
428 | 99 |
429 virtual void SetPacScriptByDataInternal(const std::string& bytes) { | 100 virtual void SetPacScriptByDataInternal(const std::string& bytes) { |
430 last_pac_contents_ = bytes; | 101 pac_bytes_ = bytes; |
431 } | 102 } |
432 | 103 |
433 virtual void CancelRequest(RequestHandle request) { | 104 const RequestsList& pending_requests() const { |
434 NOTREACHED(); | 105 return pending_requests_; |
435 } | 106 } |
436 | 107 |
| 108 const RequestsList& cancelled_requests() const { |
| 109 return cancelled_requests_; |
| 110 } |
| 111 |
| 112 const GURL& pac_url() const { |
| 113 return pac_url_; |
| 114 } |
| 115 |
| 116 const std::string& pac_bytes() const { |
| 117 return pac_bytes_; |
| 118 } |
| 119 |
| 120 void RemovePendingRequest(Request* request) { |
| 121 RequestsList::iterator it = std::find( |
| 122 pending_requests_.begin(), pending_requests_.end(), request); |
| 123 DCHECK(it != pending_requests_.end()); |
| 124 pending_requests_.erase(it); |
| 125 } |
| 126 |
| 127 protected: |
| 128 explicit MockAsyncProxyResolverBase(bool expects_pac_bytes) |
| 129 : net::ProxyResolver(expects_pac_bytes) {} |
| 130 |
437 private: | 131 private: |
438 std::string last_pac_contents_; | 132 RequestsList pending_requests_; |
| 133 RequestsList cancelled_requests_; |
| 134 GURL pac_url_; |
| 135 std::string pac_bytes_; |
439 }; | 136 }; |
440 | 137 |
441 class MockProxyResolverWithoutFetch : public net::SingleThreadedProxyResolver { | 138 class MockAsyncProxyResolver : public MockAsyncProxyResolverBase { |
442 public: | 139 public: |
443 MockProxyResolverWithoutFetch() | 140 MockAsyncProxyResolver() |
444 : net::SingleThreadedProxyResolver( | 141 : MockAsyncProxyResolverBase(false /*expects_pac_bytes*/) {} |
445 new SyncMockProxyResolverWithoutFetch) { | |
446 x = reinterpret_cast<SyncMockProxyResolverWithoutFetch*>(resolver()); | |
447 } | |
448 | |
449 // TODO(eroman): cleanup. | |
450 SyncMockProxyResolverWithoutFetch* x; | |
451 }; | 142 }; |
452 | 143 |
| 144 class MockAsyncProxyResolverExpectsBytes : public MockAsyncProxyResolverBase { |
| 145 public: |
| 146 MockAsyncProxyResolverExpectsBytes() |
| 147 : MockAsyncProxyResolverBase(true /*expects_pac_bytes*/) {} |
| 148 }; |
453 | 149 |
454 } // namespace | 150 } // namespace |
455 | 151 |
456 // A mock ProxyScriptFetcher. No result will be returned to the fetch client | 152 // A mock ProxyScriptFetcher. No result will be returned to the fetch client |
457 // until we call NotifyFetchCompletion() to set the results. | 153 // until we call NotifyFetchCompletion() to set the results. |
458 class MockProxyScriptFetcher : public net::ProxyScriptFetcher { | 154 class MockProxyScriptFetcher : public net::ProxyScriptFetcher { |
459 public: | 155 public: |
460 MockProxyScriptFetcher() : pending_request_loop_(NULL), | 156 MockProxyScriptFetcher() |
461 pending_request_callback_(NULL), pending_request_bytes_(NULL) {} | 157 : pending_request_callback_(NULL), pending_request_bytes_(NULL) { |
| 158 } |
462 | 159 |
463 // net::ProxyScriptFetcher implementation. | 160 // net::ProxyScriptFetcher implementation. |
464 virtual void Fetch(const GURL& url, std::string* bytes, | 161 virtual void Fetch(const GURL& url, |
| 162 std::string* bytes, |
465 net::CompletionCallback* callback) { | 163 net::CompletionCallback* callback) { |
466 DCHECK(!HasPendingRequest()); | 164 DCHECK(!has_pending_request()); |
467 | 165 |
468 // Save the caller's information, and have them wait. | 166 // Save the caller's information, and have them wait. |
469 pending_request_loop_ = MessageLoop::current(); | |
470 pending_request_url_ = url; | 167 pending_request_url_ = url; |
471 pending_request_callback_ = callback; | 168 pending_request_callback_ = callback; |
472 pending_request_bytes_ = bytes; | 169 pending_request_bytes_ = bytes; |
473 } | 170 } |
474 | 171 |
475 void NotifyFetchCompletion(int result, const std::string& bytes) { | 172 void NotifyFetchCompletion(int result, const std::string& bytes) { |
476 DCHECK(HasPendingRequest()); | 173 DCHECK(has_pending_request()); |
477 pending_request_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 174 *pending_request_bytes_ = bytes; |
478 this, &MockProxyScriptFetcher::DoNotifyFetchCompletion, result, bytes)); | 175 pending_request_callback_->Run(result); |
479 } | 176 } |
480 | 177 |
481 virtual void Cancel() {} | 178 virtual void Cancel() {} |
482 | 179 |
483 private: | 180 const GURL& pending_request_url() const { |
484 // Runs on |pending_request_loop_|. | 181 return pending_request_url_; |
485 void DoNotifyFetchCompletion(int result, const std::string& bytes) { | |
486 DCHECK(HasPendingRequest()); | |
487 *pending_request_bytes_ = bytes; | |
488 pending_request_callback_->Run(result); | |
489 } | 182 } |
490 | 183 |
491 bool HasPendingRequest() const { | 184 bool has_pending_request() const { |
492 return pending_request_loop_ != NULL; | 185 return pending_request_callback_ != NULL; |
493 } | 186 } |
494 | 187 |
495 MessageLoop* pending_request_loop_; | 188 private: |
496 GURL pending_request_url_; | 189 GURL pending_request_url_; |
497 net::CompletionCallback* pending_request_callback_; | 190 net::CompletionCallback* pending_request_callback_; |
498 std::string* pending_request_bytes_; | 191 std::string* pending_request_bytes_; |
499 }; | 192 }; |
500 | 193 |
501 // Template specialization so MockProxyScriptFetcher does not have to be | 194 // Template specialization so MockProxyScriptFetcher does not have to be |
502 // refcounted. | 195 // refcounted. |
503 template<> | 196 template<> |
504 void RunnableMethodTraits<MockProxyScriptFetcher>::RetainCallee( | 197 void RunnableMethodTraits<MockProxyScriptFetcher>::RetainCallee( |
505 MockProxyScriptFetcher* remover) {} | 198 MockProxyScriptFetcher* remover) {} |
506 template<> | 199 template<> |
507 void RunnableMethodTraits<MockProxyScriptFetcher>::ReleaseCallee( | 200 void RunnableMethodTraits<MockProxyScriptFetcher>::ReleaseCallee( |
508 MockProxyScriptFetcher* remover) {} | 201 MockProxyScriptFetcher* remover) {} |
509 | 202 |
510 TEST(ProxyServiceTest, Direct) { | 203 TEST(ProxyServiceTest, Direct) { |
511 SyncProxyService service(new MockProxyConfigService, | 204 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
512 new MockProxyResolver); | 205 net::ProxyService service(new MockProxyConfigService, resolver); |
513 | 206 |
514 GURL url("http://www.google.com/"); | 207 GURL url("http://www.google.com/"); |
515 | 208 |
516 net::ProxyInfo info; | 209 net::ProxyInfo info; |
517 int rv = service.ResolveProxy(url, &info); | 210 TestCompletionCallback callback; |
518 EXPECT_EQ(rv, net::OK); | 211 int rv = service.ResolveProxy(url, &info, &callback, NULL); |
| 212 EXPECT_EQ(net::OK, rv); |
| 213 EXPECT_TRUE(resolver->pending_requests().empty()); |
| 214 |
519 EXPECT_TRUE(info.is_direct()); | 215 EXPECT_TRUE(info.is_direct()); |
520 } | 216 } |
521 | 217 |
522 TEST(ProxyServiceTest, PAC) { | 218 TEST(ProxyServiceTest, PAC) { |
523 MockProxyConfigService* config_service = | 219 MockProxyConfigService* config_service = |
524 new MockProxyConfigService("http://foopy/proxy.pac"); | 220 new MockProxyConfigService("http://foopy/proxy.pac"); |
525 | 221 |
526 MockProxyResolver* resolver = new MockProxyResolver; | 222 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
527 resolver->x->info.UseNamedProxy("foopy"); | |
528 resolver->x->info_predicate_query_host = "www.google.com"; | |
529 | 223 |
530 SyncProxyService service(config_service, resolver); | 224 net::ProxyService service(config_service, resolver); |
531 | 225 |
532 GURL url("http://www.google.com/"); | 226 GURL url("http://www.google.com/"); |
533 | 227 |
534 net::ProxyInfo info; | 228 net::ProxyInfo info; |
535 int rv = service.ResolveProxy(url, &info); | 229 TestCompletionCallback callback; |
536 EXPECT_EQ(rv, net::OK); | 230 int rv = service.ResolveProxy(url, &info, &callback, NULL); |
| 231 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 232 |
| 233 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 234 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 235 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 236 |
| 237 // Set the result in proxy resolver. |
| 238 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy"); |
| 239 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 240 |
| 241 EXPECT_EQ(net::OK, callback.WaitForResult()); |
537 EXPECT_FALSE(info.is_direct()); | 242 EXPECT_FALSE(info.is_direct()); |
538 EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); | 243 EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); |
539 } | 244 } |
540 | 245 |
541 TEST(ProxyServiceTest, PAC_FailoverToDirect) { | 246 TEST(ProxyServiceTest, PAC_FailoverToDirect) { |
542 MockProxyConfigService* config_service = | 247 MockProxyConfigService* config_service = |
543 new MockProxyConfigService("http://foopy/proxy.pac"); | 248 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 249 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
544 | 250 |
545 MockProxyResolver* resolver = new MockProxyResolver; | 251 net::ProxyService service(config_service, resolver); |
546 resolver->x->info.UseNamedProxy("foopy:8080"); | |
547 resolver->x->info_predicate_query_host = "www.google.com"; | |
548 | |
549 SyncProxyService service(config_service, resolver); | |
550 | 252 |
551 GURL url("http://www.google.com/"); | 253 GURL url("http://www.google.com/"); |
552 | 254 |
553 net::ProxyInfo info; | 255 net::ProxyInfo info; |
554 int rv = service.ResolveProxy(url, &info); | 256 TestCompletionCallback callback1; |
555 EXPECT_EQ(rv, net::OK); | 257 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
| 258 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 259 |
| 260 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 261 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 262 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 263 |
| 264 // Set the result in proxy resolver. |
| 265 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080"); |
| 266 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 267 |
| 268 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
556 EXPECT_FALSE(info.is_direct()); | 269 EXPECT_FALSE(info.is_direct()); |
557 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); | 270 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); |
558 | 271 |
559 // Now, imagine that connecting to foopy:8080 fails. | 272 // Now, imagine that connecting to foopy:8080 fails. |
560 rv = service.ReconsiderProxyAfterError(url, &info); | 273 TestCompletionCallback callback2; |
561 EXPECT_EQ(rv, net::OK); | 274 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 275 EXPECT_EQ(net::OK, rv); |
562 EXPECT_TRUE(info.is_direct()); | 276 EXPECT_TRUE(info.is_direct()); |
563 } | 277 } |
564 | 278 |
565 TEST(ProxyServiceTest, PAC_FailsToDownload) { | 279 TEST(ProxyServiceTest, ProxyResolverFails) { |
566 // Test what happens when we fail to download the PAC URL. | 280 // Test what happens when the ProxyResolver fails (this could represent |
| 281 // a failure to download the PAC script in the case of ProxyResolvers which |
| 282 // do the fetch internally.) |
567 | 283 |
568 MockProxyConfigService* config_service = | 284 MockProxyConfigService* config_service = |
569 new MockProxyConfigService("http://foopy/proxy.pac"); | 285 new MockProxyConfigService("http://foopy/proxy.pac"); |
570 | 286 |
571 MockProxyResolver* resolver = new MockProxyResolver; | 287 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
572 resolver->x->info.UseNamedProxy("foopy:8080"); | |
573 resolver->x->info_predicate_query_host = "www.google.com"; | |
574 resolver->x->fail_get_proxy_for_url = true; | |
575 | 288 |
576 SyncProxyService service(config_service, resolver); | 289 net::ProxyService service(config_service, resolver); |
577 | 290 |
578 // The first resolve fails in the MockProxyResolver. | 291 // Start first resolve request. |
579 GURL url("http://www.google.com/"); | 292 GURL url("http://www.google.com/"); |
580 net::ProxyInfo info; | 293 net::ProxyInfo info; |
581 int rv = service.ResolveProxy(url, &info); | 294 TestCompletionCallback callback1; |
582 EXPECT_EQ(rv, net::ERR_FAILED); | 295 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
| 296 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 297 |
| 298 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 299 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 300 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 301 |
| 302 // Fail the first resolve request in MockAsyncProxyResolver. |
| 303 resolver->pending_requests()[0]->CompleteNow(net::ERR_FAILED); |
| 304 |
| 305 EXPECT_EQ(net::ERR_FAILED, callback1.WaitForResult()); |
583 | 306 |
584 // The second resolve request will automatically select direct connect, | 307 // The second resolve request will automatically select direct connect, |
585 // because it has cached the configuration as being bad. | 308 // because it has cached the configuration as being bad. |
586 rv = service.ResolveProxy(url, &info); | 309 TestCompletionCallback callback2; |
587 EXPECT_EQ(rv, net::OK); | 310 rv = service.ResolveProxy(url, &info, &callback2, NULL); |
| 311 EXPECT_EQ(net::OK, rv); |
588 EXPECT_TRUE(info.is_direct()); | 312 EXPECT_TRUE(info.is_direct()); |
589 | 313 EXPECT_TRUE(resolver->pending_requests().empty()); |
590 resolver->x->fail_get_proxy_for_url = false; | |
591 resolver->x->info.UseNamedProxy("foopy_valid:8080"); | |
592 | 314 |
593 // But, if that fails, then we should give the proxy config another shot | 315 // But, if that fails, then we should give the proxy config another shot |
594 // since we have never tried it with this URL before. | 316 // since we have never tried it with this URL before. |
595 rv = service.ReconsiderProxyAfterError(url, &info); | 317 TestCompletionCallback callback3; |
596 EXPECT_EQ(rv, net::OK); | 318 rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); |
| 319 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 320 |
| 321 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 322 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 323 |
| 324 // Set the result in proxy resolver. |
| 325 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); |
| 326 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 327 |
| 328 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
597 EXPECT_FALSE(info.is_direct()); | 329 EXPECT_FALSE(info.is_direct()); |
598 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); | 330 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); |
599 } | 331 } |
600 | 332 |
601 TEST(ProxyServiceTest, ProxyFallback) { | 333 TEST(ProxyServiceTest, ProxyFallback) { |
602 // Test what happens when we specify multiple proxy servers and some of them | 334 // Test what happens when we specify multiple proxy servers and some of them |
603 // are bad. | 335 // are bad. |
604 | 336 |
605 MockProxyConfigService* config_service = | 337 MockProxyConfigService* config_service = |
606 new MockProxyConfigService("http://foopy/proxy.pac"); | 338 new MockProxyConfigService("http://foopy/proxy.pac"); |
607 | 339 |
608 MockProxyResolver* resolver = new MockProxyResolver; | 340 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
609 resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); | |
610 resolver->x->info_predicate_query_host = "www.google.com"; | |
611 resolver->x->fail_get_proxy_for_url = false; | |
612 | 341 |
613 SyncProxyService service(config_service, resolver); | 342 net::ProxyService service(config_service, resolver); |
614 | 343 |
615 GURL url("http://www.google.com/"); | 344 GURL url("http://www.google.com/"); |
616 | 345 |
617 // Get the proxy information. | 346 // Get the proxy information. |
618 net::ProxyInfo info; | 347 net::ProxyInfo info; |
619 int rv = service.ResolveProxy(url, &info); | 348 TestCompletionCallback callback1; |
620 EXPECT_EQ(rv, net::OK); | 349 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
621 EXPECT_FALSE(info.is_direct()); | 350 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 351 |
| 352 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 353 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 354 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 355 |
| 356 // Set the result in proxy resolver. |
| 357 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 358 "foopy1:8080;foopy2:9090"); |
| 359 resolver->pending_requests()[0]->CompleteNow(net::OK); |
622 | 360 |
623 // The first item is valid. | 361 // The first item is valid. |
| 362 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 363 EXPECT_FALSE(info.is_direct()); |
624 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 364 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
625 | 365 |
626 // Fake an error on the proxy. | 366 // Fake an error on the proxy. |
627 rv = service.ReconsiderProxyAfterError(url, &info); | 367 TestCompletionCallback callback2; |
628 EXPECT_EQ(rv, net::OK); | 368 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 369 EXPECT_EQ(net::OK, rv); |
629 | 370 |
630 // The second proxy should be specified. | 371 // The second proxy should be specified. |
631 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 372 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
632 | 373 |
633 // Create a new resolver that returns 3 proxies. The second one is already | 374 TestCompletionCallback callback3; |
634 // known to be bad. | 375 rv = service.ResolveProxy(url, &info, &callback3, NULL); |
635 config_service->config.pac_url = GURL("http://foopy/proxy.pac"); | 376 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
636 resolver->x->info.UseNamedProxy("foopy3:7070;foopy1:8080;foopy2:9090"); | |
637 resolver->x->info_predicate_query_host = "www.google.com"; | |
638 resolver->x->fail_get_proxy_for_url = false; | |
639 | 377 |
640 rv = service.ResolveProxy(url, &info); | 378 ASSERT_EQ(1u, resolver->pending_requests().size()); |
641 EXPECT_EQ(rv, net::OK); | 379 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 380 |
| 381 // Set the result in proxy resolver -- the second result is already known |
| 382 // to be bad. |
| 383 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 384 "foopy3:7070;foopy1:8080;foopy2:9090"); |
| 385 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 386 |
| 387 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
642 EXPECT_FALSE(info.is_direct()); | 388 EXPECT_FALSE(info.is_direct()); |
643 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); | 389 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); |
644 | 390 |
645 // We fake another error. It should now try the third one. | 391 // We fake another error. It should now try the third one. |
646 rv = service.ReconsiderProxyAfterError(url, &info); | 392 TestCompletionCallback callback4; |
647 EXPECT_EQ(rv, net::OK); | 393 rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); |
| 394 EXPECT_EQ(net::OK, rv); |
648 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 395 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
649 | 396 |
650 // Fake another error, the last proxy is gone, the list should now be empty. | 397 // Fake another error, the last proxy is gone, the list should now be empty. |
651 rv = service.ReconsiderProxyAfterError(url, &info); | 398 TestCompletionCallback callback5; |
652 EXPECT_EQ(rv, net::OK); // We try direct. | 399 rv = service.ReconsiderProxyAfterError(url, &info, &callback5, NULL); |
| 400 EXPECT_EQ(net::OK, rv); // We try direct. |
653 EXPECT_TRUE(info.is_direct()); | 401 EXPECT_TRUE(info.is_direct()); |
654 | 402 |
655 // If it fails again, we don't have anything else to try. | 403 // If it fails again, we don't have anything else to try. |
656 rv = service.ReconsiderProxyAfterError(url, &info); | 404 TestCompletionCallback callback6; |
657 EXPECT_EQ(rv, net::ERR_FAILED); // We try direct. | 405 rv = service.ReconsiderProxyAfterError(url, &info, &callback6, NULL); |
| 406 EXPECT_EQ(net::ERR_FAILED, rv); |
658 | 407 |
659 // TODO(nsylvain): Test that the proxy can be retried after the delay. | 408 // TODO(nsylvain): Test that the proxy can be retried after the delay. |
660 } | 409 } |
661 | 410 |
662 TEST(ProxyServiceTest, ProxyFallback_NewSettings) { | 411 TEST(ProxyServiceTest, ProxyFallback_NewSettings) { |
663 // Test proxy failover when new settings are available. | 412 // Test proxy failover when new settings are available. |
664 | 413 |
665 MockProxyConfigService* config_service = | 414 MockProxyConfigService* config_service = |
666 new MockProxyConfigService("http://foopy/proxy.pac"); | 415 new MockProxyConfigService("http://foopy/proxy.pac"); |
667 | 416 |
668 MockProxyResolver* resolver = new MockProxyResolver; | 417 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
669 resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); | |
670 resolver->x->info_predicate_query_host = "www.google.com"; | |
671 resolver->x->fail_get_proxy_for_url = false; | |
672 | 418 |
673 SyncProxyService service(config_service, resolver); | 419 net::ProxyService service(config_service, resolver); |
674 | 420 |
675 GURL url("http://www.google.com/"); | 421 GURL url("http://www.google.com/"); |
676 | 422 |
677 // Get the proxy information. | 423 // Get the proxy information. |
678 net::ProxyInfo info; | 424 net::ProxyInfo info; |
679 int rv = service.ResolveProxy(url, &info); | 425 TestCompletionCallback callback1; |
680 EXPECT_EQ(rv, net::OK); | 426 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
681 EXPECT_FALSE(info.is_direct()); | 427 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 428 |
| 429 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 430 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 431 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 432 |
| 433 // Set the result in proxy resolver. |
| 434 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 435 "foopy1:8080;foopy2:9090"); |
| 436 resolver->pending_requests()[0]->CompleteNow(net::OK); |
682 | 437 |
683 // The first item is valid. | 438 // The first item is valid. |
| 439 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 440 EXPECT_FALSE(info.is_direct()); |
684 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 441 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
685 | 442 |
686 // Fake an error on the proxy, and also a new configuration on the proxy. | 443 // Fake an error on the proxy, and also a new configuration on the proxy. |
687 config_service->config = net::ProxyConfig(); | 444 config_service->config = net::ProxyConfig(); |
688 config_service->config.pac_url = GURL("http://foopy-new/proxy.pac"); | 445 config_service->config.pac_url = GURL("http://foopy-new/proxy.pac"); |
689 | 446 |
690 rv = service.ReconsiderProxyAfterError(url, &info); | 447 TestCompletionCallback callback2; |
691 EXPECT_EQ(rv, net::OK); | 448 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 449 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 450 |
| 451 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"), resolver->pac_url()); |
| 452 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 453 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 454 |
| 455 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 456 "foopy1:8080;foopy2:9090"); |
| 457 resolver->pending_requests()[0]->CompleteNow(net::OK); |
692 | 458 |
693 // The first proxy is still there since the configuration changed. | 459 // The first proxy is still there since the configuration changed. |
| 460 EXPECT_EQ(net::OK, callback2.WaitForResult()); |
694 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 461 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
695 | 462 |
696 // We fake another error. It should now ignore the first one. | 463 // We fake another error. It should now ignore the first one. |
697 rv = service.ReconsiderProxyAfterError(url, &info); | 464 TestCompletionCallback callback3; |
698 EXPECT_EQ(rv, net::OK); | 465 rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); |
| 466 EXPECT_EQ(net::OK, rv); |
699 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 467 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
700 | 468 |
701 // We simulate a new configuration. | 469 // We simulate a new configuration. |
702 config_service->config = net::ProxyConfig(); | 470 config_service->config = net::ProxyConfig(); |
703 config_service->config.pac_url = GURL("http://foopy-new2/proxy.pac"); | 471 config_service->config.pac_url = GURL("http://foopy-new2/proxy.pac"); |
704 | 472 |
705 // We fake anothe error. It should go back to the first proxy. | 473 // We fake another error. It should go back to the first proxy. |
706 rv = service.ReconsiderProxyAfterError(url, &info); | 474 TestCompletionCallback callback4; |
707 EXPECT_EQ(rv, net::OK); | 475 rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); |
| 476 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 477 |
| 478 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"), resolver->pac_url()); |
| 479 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 480 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 481 |
| 482 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 483 "foopy1:8080;foopy2:9090"); |
| 484 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 485 |
| 486 EXPECT_EQ(net::OK, callback4.WaitForResult()); |
708 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 487 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
709 } | 488 } |
710 | 489 |
711 TEST(ProxyServiceTest, ProxyFallback_BadConfig) { | 490 TEST(ProxyServiceTest, ProxyFallback_BadConfig) { |
712 // Test proxy failover when the configuration is bad. | 491 // Test proxy failover when the configuration is bad. |
713 | 492 |
714 MockProxyConfigService* config_service = | 493 MockProxyConfigService* config_service = |
715 new MockProxyConfigService("http://foopy/proxy.pac"); | 494 new MockProxyConfigService("http://foopy/proxy.pac"); |
716 | 495 |
717 MockProxyResolver* resolver = new MockProxyResolver; | 496 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
718 resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); | |
719 resolver->x->info_predicate_query_host = "www.google.com"; | |
720 resolver->x->fail_get_proxy_for_url = false; | |
721 | 497 |
722 SyncProxyService service(config_service, resolver); | 498 net::ProxyService service(config_service, resolver); |
723 | 499 |
724 GURL url("http://www.google.com/"); | 500 GURL url("http://www.google.com/"); |
725 | 501 |
726 // Get the proxy information. | 502 // Get the proxy information. |
727 net::ProxyInfo info; | 503 net::ProxyInfo info; |
728 int rv = service.ResolveProxy(url, &info); | 504 TestCompletionCallback callback1; |
729 EXPECT_EQ(rv, net::OK); | 505 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
730 EXPECT_FALSE(info.is_direct()); | 506 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 507 |
| 508 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 509 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 510 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 511 |
| 512 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 513 "foopy1:8080;foopy2:9090"); |
| 514 resolver->pending_requests()[0]->CompleteNow(net::OK); |
731 | 515 |
732 // The first item is valid. | 516 // The first item is valid. |
| 517 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 518 EXPECT_FALSE(info.is_direct()); |
733 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 519 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
734 | 520 |
735 // Fake a proxy error. | 521 // Fake a proxy error. |
736 rv = service.ReconsiderProxyAfterError(url, &info); | 522 TestCompletionCallback callback2; |
737 EXPECT_EQ(rv, net::OK); | 523 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 524 EXPECT_EQ(net::OK, rv); |
738 | 525 |
739 // The first proxy is ignored, and the second one is selected. | 526 // The first proxy is ignored, and the second one is selected. |
740 EXPECT_FALSE(info.is_direct()); | 527 EXPECT_FALSE(info.is_direct()); |
741 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 528 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
742 | 529 |
743 // Fake a PAC failure. | 530 // Fake a PAC failure. |
744 net::ProxyInfo info2; | 531 net::ProxyInfo info2; |
745 resolver->x->fail_get_proxy_for_url = true; | 532 TestCompletionCallback callback3; |
746 rv = service.ResolveProxy(url, &info2); | 533 rv = service.ResolveProxy(url, &info2, &callback3, NULL); |
747 EXPECT_EQ(rv, net::ERR_FAILED); | 534 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 535 |
| 536 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 537 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 538 |
| 539 resolver->pending_requests()[0]->CompleteNow(net::ERR_FAILED); |
748 | 540 |
749 // No proxy servers are returned. It's a direct connection. | 541 // No proxy servers are returned. It's a direct connection. |
| 542 EXPECT_EQ(net::ERR_FAILED, callback3.WaitForResult()); |
750 EXPECT_TRUE(info2.is_direct()); | 543 EXPECT_TRUE(info2.is_direct()); |
751 | 544 |
752 // The PAC is now fixed and will return a proxy server. | 545 // The PAC will now be fixed and will return a proxy server. |
753 // It should also clear the list of bad proxies. | 546 // It should also clear the list of bad proxies. |
754 resolver->x->fail_get_proxy_for_url = false; | |
755 | 547 |
756 // Try to resolve, it will still return "direct" because we have no reason | 548 // Try to resolve, it will still return "direct" because we have no reason |
757 // to check the config since everything works. | 549 // to check the config since everything works. |
758 net::ProxyInfo info3; | 550 net::ProxyInfo info3; |
759 rv = service.ResolveProxy(url, &info3); | 551 TestCompletionCallback callback4; |
760 EXPECT_EQ(rv, net::OK); | 552 rv = service.ResolveProxy(url, &info3, &callback4, NULL); |
| 553 EXPECT_EQ(net::OK, rv); |
761 EXPECT_TRUE(info3.is_direct()); | 554 EXPECT_TRUE(info3.is_direct()); |
762 | 555 |
763 // But if the direct connection fails, we check if the ProxyInfo tried to | 556 // But if the direct connection fails, we check if the ProxyInfo tried to |
764 // resolve the proxy before, and if not (like in this case), we give the | 557 // resolve the proxy before, and if not (like in this case), we give the |
765 // PAC another try. | 558 // PAC another try. |
766 rv = service.ReconsiderProxyAfterError(url, &info3); | 559 TestCompletionCallback callback5; |
767 EXPECT_EQ(rv, net::OK); | 560 rv = service.ReconsiderProxyAfterError(url, &info3, &callback5, NULL); |
| 561 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 562 |
| 563 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 564 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 565 |
| 566 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 567 "foopy1:8080;foopy2:9090"); |
| 568 resolver->pending_requests()[0]->CompleteNow(net::OK); |
768 | 569 |
769 // The first proxy is still there since the list of bad proxies got cleared. | 570 // The first proxy is still there since the list of bad proxies got cleared. |
| 571 EXPECT_EQ(net::OK, callback5.WaitForResult()); |
770 EXPECT_FALSE(info3.is_direct()); | 572 EXPECT_FALSE(info3.is_direct()); |
771 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); | 573 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); |
772 } | 574 } |
773 | 575 |
774 TEST(ProxyServiceTest, ProxyBypassList) { | 576 TEST(ProxyServiceTest, ProxyBypassList) { |
775 // Test what happens when a proxy bypass list is specified. | 577 // Test what happens when a proxy bypass list is specified. |
776 | 578 |
777 net::ProxyInfo info; | 579 net::ProxyInfo info; |
778 net::ProxyConfig config; | 580 net::ProxyConfig config; |
779 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); | 581 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); |
780 config.auto_detect = false; | 582 config.auto_detect = false; |
781 config.proxy_bypass_local_names = true; | 583 config.proxy_bypass_local_names = true; |
782 | 584 |
783 { | 585 { |
784 SyncProxyService service(new MockProxyConfigService(config), | 586 net::ProxyService service(new MockProxyConfigService(config), |
785 new MockProxyResolver()); | 587 new MockAsyncProxyResolver()); |
786 GURL url("http://www.google.com/"); | 588 GURL url("http://www.google.com/"); |
787 // Get the proxy information. | 589 // Get the proxy information. |
788 int rv = service.ResolveProxy(url, &info); | 590 TestCompletionCallback callback; |
789 EXPECT_EQ(rv, net::OK); | 591 int rv = service.ResolveProxy(url, &info, &callback, NULL); |
| 592 EXPECT_EQ(net::OK, rv); |
790 EXPECT_FALSE(info.is_direct()); | 593 EXPECT_FALSE(info.is_direct()); |
791 } | 594 } |
792 | 595 |
793 { | 596 { |
794 SyncProxyService service(new MockProxyConfigService(config), | 597 net::ProxyService service(new MockProxyConfigService(config), |
795 new MockProxyResolver()); | 598 new MockAsyncProxyResolver()); |
796 GURL test_url("local"); | 599 GURL test_url("local"); |
797 int rv = service.ResolveProxy(test_url, &info); | 600 TestCompletionCallback callback; |
798 EXPECT_EQ(rv, net::OK); | 601 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 602 EXPECT_EQ(net::OK, rv); |
799 EXPECT_TRUE(info.is_direct()); | 603 EXPECT_TRUE(info.is_direct()); |
800 } | 604 } |
801 | 605 |
802 config.proxy_bypass.clear(); | 606 config.proxy_bypass.clear(); |
803 config.proxy_bypass.push_back("*.org"); | 607 config.proxy_bypass.push_back("*.org"); |
804 config.proxy_bypass_local_names = true; | 608 config.proxy_bypass_local_names = true; |
805 { | 609 { |
806 SyncProxyService service(new MockProxyConfigService(config), | 610 net::ProxyService service(new MockProxyConfigService(config), |
807 new MockProxyResolver); | 611 new MockAsyncProxyResolver); |
808 GURL test_url("http://www.webkit.org"); | 612 GURL test_url("http://www.webkit.org"); |
809 int rv = service.ResolveProxy(test_url, &info); | 613 TestCompletionCallback callback; |
810 EXPECT_EQ(rv, net::OK); | 614 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 615 EXPECT_EQ(net::OK, rv); |
811 EXPECT_TRUE(info.is_direct()); | 616 EXPECT_TRUE(info.is_direct()); |
812 } | 617 } |
813 | 618 |
814 config.proxy_bypass.clear(); | 619 config.proxy_bypass.clear(); |
815 config.proxy_bypass.push_back("*.org"); | 620 config.proxy_bypass.push_back("*.org"); |
816 config.proxy_bypass.push_back("7*"); | 621 config.proxy_bypass.push_back("7*"); |
817 config.proxy_bypass_local_names = true; | 622 config.proxy_bypass_local_names = true; |
818 { | 623 { |
819 SyncProxyService service(new MockProxyConfigService(config), | 624 net::ProxyService service(new MockProxyConfigService(config), |
820 new MockProxyResolver); | 625 new MockAsyncProxyResolver); |
821 GURL test_url("http://74.125.19.147"); | 626 GURL test_url("http://74.125.19.147"); |
822 int rv = service.ResolveProxy(test_url, &info); | 627 TestCompletionCallback callback; |
823 EXPECT_EQ(rv, net::OK); | 628 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 629 EXPECT_EQ(net::OK, rv); |
824 EXPECT_TRUE(info.is_direct()); | 630 EXPECT_TRUE(info.is_direct()); |
825 } | 631 } |
826 | 632 |
827 config.proxy_bypass.clear(); | 633 config.proxy_bypass.clear(); |
828 config.proxy_bypass.push_back("*.org"); | 634 config.proxy_bypass.push_back("*.org"); |
829 config.proxy_bypass_local_names = true; | 635 config.proxy_bypass_local_names = true; |
830 { | 636 { |
831 SyncProxyService service(new MockProxyConfigService(config), | 637 net::ProxyService service(new MockProxyConfigService(config), |
832 new MockProxyResolver); | 638 new MockAsyncProxyResolver); |
833 GURL test_url("http://www.msn.com"); | 639 GURL test_url("http://www.msn.com"); |
834 int rv = service.ResolveProxy(test_url, &info); | 640 TestCompletionCallback callback; |
835 EXPECT_EQ(rv, net::OK); | 641 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 642 EXPECT_EQ(net::OK, rv); |
836 EXPECT_FALSE(info.is_direct()); | 643 EXPECT_FALSE(info.is_direct()); |
837 } | 644 } |
838 | 645 |
839 config.proxy_bypass.clear(); | 646 config.proxy_bypass.clear(); |
840 config.proxy_bypass.push_back("*.MSN.COM"); | 647 config.proxy_bypass.push_back("*.MSN.COM"); |
841 config.proxy_bypass_local_names = true; | 648 config.proxy_bypass_local_names = true; |
842 { | 649 { |
843 SyncProxyService service(new MockProxyConfigService(config), | 650 net::ProxyService service(new MockProxyConfigService(config), |
844 new MockProxyResolver); | 651 new MockAsyncProxyResolver); |
845 GURL test_url("http://www.msnbc.msn.com"); | 652 GURL test_url("http://www.msnbc.msn.com"); |
846 int rv = service.ResolveProxy(test_url, &info); | 653 TestCompletionCallback callback; |
847 EXPECT_EQ(rv, net::OK); | 654 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 655 EXPECT_EQ(net::OK, rv); |
848 EXPECT_TRUE(info.is_direct()); | 656 EXPECT_TRUE(info.is_direct()); |
849 } | 657 } |
850 | 658 |
851 config.proxy_bypass.clear(); | 659 config.proxy_bypass.clear(); |
852 config.proxy_bypass.push_back("*.msn.com"); | 660 config.proxy_bypass.push_back("*.msn.com"); |
853 config.proxy_bypass_local_names = true; | 661 config.proxy_bypass_local_names = true; |
854 { | 662 { |
855 SyncProxyService service(new MockProxyConfigService(config), | 663 net::ProxyService service(new MockProxyConfigService(config), |
856 new MockProxyResolver); | 664 new MockAsyncProxyResolver); |
857 GURL test_url("HTTP://WWW.MSNBC.MSN.COM"); | 665 GURL test_url("HTTP://WWW.MSNBC.MSN.COM"); |
858 int rv = service.ResolveProxy(test_url, &info); | 666 TestCompletionCallback callback; |
859 EXPECT_EQ(rv, net::OK); | 667 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 668 EXPECT_EQ(net::OK, rv); |
860 EXPECT_TRUE(info.is_direct()); | 669 EXPECT_TRUE(info.is_direct()); |
861 } | 670 } |
862 } | 671 } |
863 | 672 |
864 TEST(ProxyServiceTest, ProxyBypassListWithPorts) { | 673 TEST(ProxyServiceTest, ProxyBypassListWithPorts) { |
865 // Test port specification in bypass list entries. | 674 // Test port specification in bypass list entries. |
866 net::ProxyInfo info; | 675 net::ProxyInfo info; |
867 net::ProxyConfig config; | 676 net::ProxyConfig config; |
868 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); | 677 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); |
869 config.auto_detect = false; | 678 config.auto_detect = false; |
870 config.proxy_bypass_local_names = false; | 679 config.proxy_bypass_local_names = false; |
871 | 680 |
872 config.proxy_bypass.clear(); | 681 config.proxy_bypass.clear(); |
873 config.proxy_bypass.push_back("*.example.com:99"); | 682 config.proxy_bypass.push_back("*.example.com:99"); |
874 { | 683 { |
875 SyncProxyService service(new MockProxyConfigService(config), | 684 net::ProxyService service(new MockProxyConfigService(config), |
876 new MockProxyResolver); | 685 new MockAsyncProxyResolver); |
877 { | 686 { |
878 GURL test_url("http://www.example.com:99"); | 687 GURL test_url("http://www.example.com:99"); |
879 int rv = service.ResolveProxy(test_url, &info); | 688 TestCompletionCallback callback; |
880 EXPECT_EQ(rv, net::OK); | 689 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 690 EXPECT_EQ(net::OK, rv); |
881 EXPECT_TRUE(info.is_direct()); | 691 EXPECT_TRUE(info.is_direct()); |
882 } | 692 } |
883 { | 693 { |
884 GURL test_url("http://www.example.com:100"); | 694 GURL test_url("http://www.example.com:100"); |
885 int rv = service.ResolveProxy(test_url, &info); | 695 TestCompletionCallback callback; |
886 EXPECT_EQ(rv, net::OK); | 696 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 697 EXPECT_EQ(net::OK, rv); |
887 EXPECT_FALSE(info.is_direct()); | 698 EXPECT_FALSE(info.is_direct()); |
888 } | 699 } |
889 { | 700 { |
890 GURL test_url("http://www.example.com"); | 701 GURL test_url("http://www.example.com"); |
891 int rv = service.ResolveProxy(test_url, &info); | 702 TestCompletionCallback callback; |
892 EXPECT_EQ(rv, net::OK); | 703 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 704 EXPECT_EQ(net::OK, rv); |
893 EXPECT_FALSE(info.is_direct()); | 705 EXPECT_FALSE(info.is_direct()); |
894 } | 706 } |
895 } | 707 } |
896 | 708 |
897 config.proxy_bypass.clear(); | 709 config.proxy_bypass.clear(); |
898 config.proxy_bypass.push_back("*.example.com:80"); | 710 config.proxy_bypass.push_back("*.example.com:80"); |
899 { | 711 { |
900 SyncProxyService service(new MockProxyConfigService(config), | 712 net::ProxyService service(new MockProxyConfigService(config), |
901 new MockProxyResolver); | 713 new MockAsyncProxyResolver); |
902 GURL test_url("http://www.example.com"); | 714 GURL test_url("http://www.example.com"); |
903 int rv = service.ResolveProxy(test_url, &info); | 715 TestCompletionCallback callback; |
904 EXPECT_EQ(rv, net::OK); | 716 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 717 EXPECT_EQ(net::OK, rv); |
905 EXPECT_TRUE(info.is_direct()); | 718 EXPECT_TRUE(info.is_direct()); |
906 } | 719 } |
907 | 720 |
908 config.proxy_bypass.clear(); | 721 config.proxy_bypass.clear(); |
909 config.proxy_bypass.push_back("*.example.com"); | 722 config.proxy_bypass.push_back("*.example.com"); |
910 { | 723 { |
911 SyncProxyService service(new MockProxyConfigService(config), | 724 net::ProxyService service(new MockProxyConfigService(config), |
912 new MockProxyResolver); | 725 new MockAsyncProxyResolver); |
913 GURL test_url("http://www.example.com:99"); | 726 GURL test_url("http://www.example.com:99"); |
914 int rv = service.ResolveProxy(test_url, &info); | 727 TestCompletionCallback callback; |
915 EXPECT_EQ(rv, net::OK); | 728 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 729 EXPECT_EQ(net::OK, rv); |
916 EXPECT_TRUE(info.is_direct()); | 730 EXPECT_TRUE(info.is_direct()); |
917 } | 731 } |
918 | 732 |
919 // IPv6 with port. | 733 // IPv6 with port. |
920 config.proxy_bypass.clear(); | 734 config.proxy_bypass.clear(); |
921 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99"); | 735 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99"); |
922 { | 736 { |
923 SyncProxyService service(new MockProxyConfigService(config), | 737 net::ProxyService service(new MockProxyConfigService(config), |
924 new MockProxyResolver); | 738 new MockAsyncProxyResolver); |
925 { | 739 { |
926 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); | 740 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); |
927 int rv = service.ResolveProxy(test_url, &info); | 741 TestCompletionCallback callback; |
928 EXPECT_EQ(rv, net::OK); | 742 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 743 EXPECT_EQ(net::OK, rv); |
929 EXPECT_TRUE(info.is_direct()); | 744 EXPECT_TRUE(info.is_direct()); |
930 } | 745 } |
931 { | 746 { |
932 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); | 747 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); |
933 int rv = service.ResolveProxy(test_url, &info); | 748 TestCompletionCallback callback; |
934 EXPECT_EQ(rv, net::OK); | 749 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 750 EXPECT_EQ(net::OK, rv); |
935 EXPECT_FALSE(info.is_direct()); | 751 EXPECT_FALSE(info.is_direct()); |
936 } | 752 } |
937 } | 753 } |
938 | 754 |
939 // IPv6 without port. The bypass entry ought to work without the | 755 // IPv6 without port. The bypass entry ought to work without the |
940 // brackets, but the bypass matching logic in ProxyService is | 756 // brackets, but the bypass matching logic in ProxyService is |
941 // currently limited. | 757 // currently limited. |
942 config.proxy_bypass.clear(); | 758 config.proxy_bypass.clear(); |
943 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]"); | 759 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]"); |
944 { | 760 { |
945 SyncProxyService service(new MockProxyConfigService(config), | 761 net::ProxyService service(new MockProxyConfigService(config), |
946 new MockProxyResolver); | 762 new MockAsyncProxyResolver); |
947 { | 763 { |
948 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); | 764 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); |
949 int rv = service.ResolveProxy(test_url, &info); | 765 TestCompletionCallback callback; |
950 EXPECT_EQ(rv, net::OK); | 766 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 767 EXPECT_EQ(net::OK, rv); |
951 EXPECT_TRUE(info.is_direct()); | 768 EXPECT_TRUE(info.is_direct()); |
952 } | 769 } |
953 { | 770 { |
954 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); | 771 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); |
955 int rv = service.ResolveProxy(test_url, &info); | 772 TestCompletionCallback callback; |
956 EXPECT_EQ(rv, net::OK); | 773 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 774 EXPECT_EQ(net::OK, rv); |
957 EXPECT_TRUE(info.is_direct()); | 775 EXPECT_TRUE(info.is_direct()); |
958 } | 776 } |
959 } | 777 } |
960 } | 778 } |
961 | 779 |
962 TEST(ProxyServiceTest, PerProtocolProxyTests) { | 780 TEST(ProxyServiceTest, PerProtocolProxyTests) { |
963 net::ProxyConfig config; | 781 net::ProxyConfig config; |
964 config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080"); | 782 config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080"); |
965 config.auto_detect = false; | 783 config.auto_detect = false; |
966 | 784 { |
967 SyncProxyService service1(new MockProxyConfigService(config), | 785 net::ProxyService service(new MockProxyConfigService(config), |
968 new MockProxyResolver); | 786 new MockAsyncProxyResolver); |
969 GURL test_url1("http://www.msn.com"); | 787 GURL test_url("http://www.msn.com"); |
970 net::ProxyInfo info1; | 788 net::ProxyInfo info; |
971 int rv = service1.ResolveProxy(test_url1, &info1); | 789 TestCompletionCallback callback; |
972 EXPECT_EQ(rv, net::OK); | 790 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
973 EXPECT_FALSE(info1.is_direct()); | 791 EXPECT_EQ(net::OK, rv); |
974 EXPECT_EQ("foopy1:8080", info1.proxy_server().ToURI()); | 792 EXPECT_FALSE(info.is_direct()); |
975 | 793 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
976 SyncProxyService service2(new MockProxyConfigService(config), | 794 } |
977 new MockProxyResolver); | 795 { |
978 GURL test_url2("ftp://ftp.google.com"); | 796 net::ProxyService service(new MockProxyConfigService(config), |
979 net::ProxyInfo info2; | 797 new MockAsyncProxyResolver); |
980 rv = service2.ResolveProxy(test_url2, &info2); | 798 GURL test_url("ftp://ftp.google.com"); |
981 EXPECT_EQ(rv, net::OK); | 799 net::ProxyInfo info; |
982 EXPECT_TRUE(info2.is_direct()); | 800 TestCompletionCallback callback; |
983 EXPECT_EQ("direct://", info2.proxy_server().ToURI()); | 801 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
984 | 802 EXPECT_EQ(net::OK, rv); |
985 SyncProxyService service3(new MockProxyConfigService(config), | 803 EXPECT_TRUE(info.is_direct()); |
986 new MockProxyResolver); | 804 EXPECT_EQ("direct://", info.proxy_server().ToURI()); |
987 GURL test_url3("https://webbranch.techcu.com"); | 805 } |
988 net::ProxyInfo info3; | 806 { |
989 rv = service3.ResolveProxy(test_url3, &info3); | 807 net::ProxyService service(new MockProxyConfigService(config), |
990 EXPECT_EQ(rv, net::OK); | 808 new MockAsyncProxyResolver); |
991 EXPECT_FALSE(info3.is_direct()); | 809 GURL test_url("https://webbranch.techcu.com"); |
992 EXPECT_EQ("foopy2:8080", info3.proxy_server().ToURI()); | 810 net::ProxyInfo info; |
993 | 811 TestCompletionCallback callback; |
994 config.proxy_rules.ParseFromString("foopy1:8080"); | 812 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
995 SyncProxyService service4(new MockProxyConfigService(config), | 813 EXPECT_EQ(net::OK, rv); |
996 new MockProxyResolver); | 814 EXPECT_FALSE(info.is_direct()); |
997 GURL test_url4("www.microsoft.com"); | 815 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); |
998 net::ProxyInfo info4; | 816 } |
999 rv = service4.ResolveProxy(test_url4, &info4); | 817 { |
1000 EXPECT_EQ(rv, net::OK); | 818 config.proxy_rules.ParseFromString("foopy1:8080"); |
1001 EXPECT_FALSE(info4.is_direct()); | 819 net::ProxyService service(new MockProxyConfigService(config), |
1002 EXPECT_EQ("foopy1:8080", info4.proxy_server().ToURI()); | 820 new MockAsyncProxyResolver); |
| 821 GURL test_url("www.microsoft.com"); |
| 822 net::ProxyInfo info; |
| 823 TestCompletionCallback callback; |
| 824 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 825 EXPECT_EQ(net::OK, rv); |
| 826 EXPECT_FALSE(info.is_direct()); |
| 827 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 828 } |
1003 } | 829 } |
1004 | 830 |
1005 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries | 831 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries |
1006 // fall back to the SOCKS proxy. | 832 // fall back to the SOCKS proxy. |
1007 TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { | 833 TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { |
1008 net::ProxyConfig config; | 834 net::ProxyConfig config; |
1009 config.proxy_rules.ParseFromString("http=foopy1:8080;socks=foopy2:1080"); | 835 config.proxy_rules.ParseFromString("http=foopy1:8080;socks=foopy2:1080"); |
1010 config.auto_detect = false; | 836 config.auto_detect = false; |
1011 EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, | 837 EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, |
1012 config.proxy_rules.type); | 838 config.proxy_rules.type); |
1013 | 839 |
1014 SyncProxyService service1(new MockProxyConfigService(config), | 840 { |
1015 new MockProxyResolver); | 841 net::ProxyService service(new MockProxyConfigService(config), |
1016 GURL test_url1("http://www.msn.com"); | 842 new MockAsyncProxyResolver); |
1017 net::ProxyInfo info1; | 843 GURL test_url("http://www.msn.com"); |
1018 int rv = service1.ResolveProxy(test_url1, &info1); | 844 net::ProxyInfo info; |
1019 EXPECT_EQ(net::OK, rv); | 845 TestCompletionCallback callback; |
1020 EXPECT_FALSE(info1.is_direct()); | 846 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
1021 EXPECT_EQ("foopy1:8080", info1.proxy_server().ToURI()); | 847 EXPECT_EQ(net::OK, rv); |
1022 | 848 EXPECT_FALSE(info.is_direct()); |
1023 SyncProxyService service2(new MockProxyConfigService(config), | 849 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
1024 new MockProxyResolver); | 850 } |
1025 GURL test_url2("ftp://ftp.google.com"); | 851 { |
1026 net::ProxyInfo info2; | 852 net::ProxyService service(new MockProxyConfigService(config), |
1027 rv = service2.ResolveProxy(test_url2, &info2); | 853 new MockAsyncProxyResolver); |
1028 EXPECT_EQ(net::OK, rv); | 854 GURL test_url("ftp://ftp.google.com"); |
1029 EXPECT_FALSE(info2.is_direct()); | 855 net::ProxyInfo info; |
1030 EXPECT_EQ("socks4://foopy2:1080", info2.proxy_server().ToURI()); | 856 TestCompletionCallback callback; |
1031 | 857 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
1032 SyncProxyService service3(new MockProxyConfigService(config), | 858 EXPECT_EQ(net::OK, rv); |
1033 new MockProxyResolver); | 859 EXPECT_FALSE(info.is_direct()); |
1034 GURL test_url3("https://webbranch.techcu.com"); | 860 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); |
1035 net::ProxyInfo info3; | 861 } |
1036 rv = service3.ResolveProxy(test_url3, &info3); | 862 { |
1037 EXPECT_EQ(net::OK, rv); | 863 net::ProxyService service(new MockProxyConfigService(config), |
1038 EXPECT_FALSE(info3.is_direct()); | 864 new MockAsyncProxyResolver); |
1039 EXPECT_EQ("socks4://foopy2:1080", info3.proxy_server().ToURI()); | 865 GURL test_url("https://webbranch.techcu.com"); |
1040 | 866 net::ProxyInfo info; |
1041 SyncProxyService service4(new MockProxyConfigService(config), | 867 TestCompletionCallback callback; |
1042 new MockProxyResolver); | 868 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
1043 GURL test_url4("www.microsoft.com"); | 869 EXPECT_EQ(net::OK, rv); |
1044 net::ProxyInfo info4; | 870 EXPECT_FALSE(info.is_direct()); |
1045 rv = service4.ResolveProxy(test_url4, &info4); | 871 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); |
1046 EXPECT_EQ(net::OK, rv); | 872 } |
1047 EXPECT_FALSE(info4.is_direct()); | 873 { |
1048 EXPECT_EQ("socks4://foopy2:1080", info4.proxy_server().ToURI()); | 874 net::ProxyService service(new MockProxyConfigService(config), |
| 875 new MockAsyncProxyResolver); |
| 876 GURL test_url("www.microsoft.com"); |
| 877 net::ProxyInfo info; |
| 878 TestCompletionCallback callback; |
| 879 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 880 EXPECT_EQ(net::OK, rv); |
| 881 EXPECT_FALSE(info.is_direct()); |
| 882 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); |
| 883 } |
1049 } | 884 } |
1050 | 885 |
1051 // Test cancellation of a queued request. | 886 // Test cancellation of an in-progress request. |
1052 TEST(ProxyServiceTest, CancelQueuedRequest) { | 887 TEST(ProxyServiceTest, CancelInProgressRequest) { |
1053 MockProxyConfigService* config_service = | 888 MockProxyConfigService* config_service = |
1054 new MockProxyConfigService("http://foopy/proxy.pac"); | 889 new MockProxyConfigService("http://foopy/proxy.pac"); |
1055 | 890 |
1056 BlockableProxyResolver* resolver = new BlockableProxyResolver; | 891 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
1057 | 892 |
1058 ProxyServiceWithFutures service(config_service, resolver); | 893 net::ProxyService service(config_service, resolver); |
1059 | |
1060 // Cause requests to pile up, by having them block in the PAC thread. | |
1061 resolver->x->Block(); | |
1062 | 894 |
1063 // Start 3 requests. | 895 // Start 3 requests. |
1064 scoped_refptr<ResultFuture> result1; | |
1065 service.ResolveProxy(&result1, GURL("http://request1")); | |
1066 | 896 |
1067 scoped_refptr<ResultFuture> result2; | 897 net::ProxyInfo info1; |
1068 service.ResolveProxy(&result2, GURL("http://request2")); | 898 TestCompletionCallback callback1; |
| 899 int rv = service.ResolveProxy( |
| 900 GURL("http://request1"), &info1, &callback1, NULL); |
| 901 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 902 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 903 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); |
1069 | 904 |
1070 scoped_refptr<ResultFuture> result3; | 905 net::ProxyInfo info2; |
1071 service.ResolveProxy(&result3, GURL("http://request3")); | 906 TestCompletionCallback callback2; |
| 907 net::ProxyService::PacRequest* request2; |
| 908 rv = service.ResolveProxy( |
| 909 GURL("http://request2"), &info2, &callback2, &request2); |
| 910 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 911 ASSERT_EQ(2u, resolver->pending_requests().size()); |
| 912 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); |
1072 | 913 |
1073 // Wait until the first request has become blocked in the PAC thread. | 914 net::ProxyInfo info3; |
1074 resolver->x->WaitUntilBlocked(); | 915 TestCompletionCallback callback3; |
| 916 rv = service.ResolveProxy( |
| 917 GURL("http://request3"), &info3, &callback3, NULL); |
| 918 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 919 ASSERT_EQ(3u, resolver->pending_requests().size()); |
| 920 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); |
1075 | 921 |
1076 // Cancel the second request | 922 // Cancel the second request |
1077 result2->Cancel(); | 923 service.CancelPacRequest(request2); |
1078 | 924 |
1079 // Unblock the PAC thread. | 925 ASSERT_EQ(2u, resolver->pending_requests().size()); |
1080 resolver->x->Unblock(); | 926 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); |
| 927 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url()); |
1081 | 928 |
1082 // Wait for the final request to complete. | 929 // Complete the two un-cancelled requests. |
1083 result3->WaitUntilCompleted(); | 930 // We complete the last one first, just to mix it up a bit. |
| 931 resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80"); |
| 932 resolver->pending_requests()[1]->CompleteNow(net::OK); |
1084 | 933 |
1085 // Verify that requests ran as expected. | 934 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); |
| 935 resolver->pending_requests()[0]->CompleteNow(net::OK); |
1086 | 936 |
1087 EXPECT_TRUE(result1->IsCompleted()); | 937 // Complete and verify that requests ran as expected. |
1088 EXPECT_EQ(net::OK, result1->GetResultCode()); | 938 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
1089 EXPECT_EQ("request1:80", result1->GetProxyInfo().proxy_server().ToURI()); | 939 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); |
1090 | 940 |
1091 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. | 941 EXPECT_FALSE(callback2.have_result()); // Cancelled. |
| 942 ASSERT_EQ(1u, resolver->cancelled_requests().size()); |
| 943 EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url()); |
1092 | 944 |
1093 EXPECT_TRUE(result3->IsCompleted()); | 945 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
1094 EXPECT_EQ(net::OK, result3->GetResultCode()); | 946 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); |
1095 EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); | |
1096 } | |
1097 | |
1098 // Test cancellation of an in-progress request. | |
1099 TEST(ProxyServiceTest, CancelInprogressRequest) { | |
1100 MockProxyConfigService* config_service = | |
1101 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1102 | |
1103 BlockableProxyResolver* resolver = new BlockableProxyResolver; | |
1104 | |
1105 ProxyServiceWithFutures service(config_service, resolver); | |
1106 | |
1107 // Cause requests to pile up, by having them block in the PAC thread. | |
1108 resolver->x->Block(); | |
1109 | |
1110 // Start 3 requests. | |
1111 scoped_refptr<ResultFuture> result1; | |
1112 service.ResolveProxy(&result1, GURL("http://request1")); | |
1113 | |
1114 scoped_refptr<ResultFuture> result2; | |
1115 service.ResolveProxy(&result2, GURL("http://request2")); | |
1116 | |
1117 scoped_refptr<ResultFuture> result3; | |
1118 service.ResolveProxy(&result3, GURL("http://request3")); | |
1119 | |
1120 // Wait until the first request has become blocked in the PAC thread. | |
1121 resolver->x->WaitUntilBlocked(); | |
1122 | |
1123 // Cancel the first request | |
1124 result1->Cancel(); | |
1125 | |
1126 // Unblock the PAC thread. | |
1127 resolver->x->Unblock(); | |
1128 | |
1129 // Wait for the final request to complete. | |
1130 result3->WaitUntilCompleted(); | |
1131 | |
1132 // Verify that requests ran as expected. | |
1133 | |
1134 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. | |
1135 | |
1136 EXPECT_TRUE(result2->IsCompleted()); | |
1137 EXPECT_EQ(net::OK, result2->GetResultCode()); | |
1138 EXPECT_EQ("request2:80", result2->GetProxyInfo().proxy_server().ToURI()); | |
1139 | |
1140 EXPECT_TRUE(result3->IsCompleted()); | |
1141 EXPECT_EQ(net::OK, result3->GetResultCode()); | |
1142 EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); | |
1143 } | 947 } |
1144 | 948 |
1145 // Test the initial PAC download for ProxyResolverWithoutFetch. | 949 // Test the initial PAC download for ProxyResolverWithoutFetch. |
1146 TEST(ProxyServiceTest, InitialPACScriptDownload) { | 950 TEST(ProxyServiceTest, InitialPACScriptDownload) { |
1147 MockProxyConfigService* config_service = | 951 MockProxyConfigService* config_service = |
1148 new MockProxyConfigService("http://foopy/proxy.pac"); | 952 new MockProxyConfigService("http://foopy/proxy.pac"); |
1149 | 953 |
1150 MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; | 954 MockAsyncProxyResolverExpectsBytes* resolver = |
| 955 new MockAsyncProxyResolverExpectsBytes; |
1151 | 956 |
1152 ProxyServiceWithFutures service(config_service, resolver); | 957 net::ProxyService service(config_service, resolver); |
1153 | 958 |
1154 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | 959 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; |
1155 service.SetProxyScriptFetcher(fetcher); | 960 service.SetProxyScriptFetcher(fetcher); |
1156 | 961 |
1157 // Start 3 requests. | 962 // Start 3 requests. |
1158 scoped_refptr<ResultFuture> result1; | |
1159 service.ResolveProxy(&result1, GURL("http://request1")); | |
1160 | 963 |
1161 scoped_refptr<ResultFuture> result2; | 964 net::ProxyInfo info1; |
1162 service.ResolveProxy(&result2, GURL("http://request2")); | 965 TestCompletionCallback callback1; |
| 966 int rv = service.ResolveProxy( |
| 967 GURL("http://request1"), &info1, &callback1, NULL); |
| 968 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
1163 | 969 |
1164 scoped_refptr<ResultFuture> result3; | 970 // The first request should have triggered download of PAC script. |
1165 service.ResolveProxy(&result3, GURL("http://request3")); | 971 EXPECT_TRUE(fetcher->has_pending_request()); |
| 972 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); |
| 973 |
| 974 net::ProxyInfo info2; |
| 975 TestCompletionCallback callback2; |
| 976 rv = service.ResolveProxy( |
| 977 GURL("http://request2"), &info2, &callback2, NULL); |
| 978 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 979 |
| 980 net::ProxyInfo info3; |
| 981 TestCompletionCallback callback3; |
| 982 rv = service.ResolveProxy( |
| 983 GURL("http://request3"), &info3, &callback3, NULL); |
| 984 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 985 |
| 986 // Nothing has been sent to the resolver yet. |
| 987 EXPECT_TRUE(resolver->pending_requests().empty()); |
1166 | 988 |
1167 // At this point the ProxyService should be waiting for the | 989 // At this point the ProxyService should be waiting for the |
1168 // ProxyScriptFetcher to invoke its completion callback, notifying it of | 990 // ProxyScriptFetcher to invoke its completion callback, notifying it of |
1169 // PAC script download completion. | 991 // PAC script download completion. |
1170 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); | 992 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); |
1171 | 993 |
1172 // Complete all the requests. | 994 // Now that the PAC script is downloaded, everything should have been sent |
1173 result3->WaitUntilCompleted(); | 995 // over to the proxy resolver. |
| 996 EXPECT_EQ("pac-v1", resolver->pac_bytes()); |
| 997 ASSERT_EQ(3u, resolver->pending_requests().size()); |
| 998 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); |
| 999 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); |
| 1000 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); |
1174 | 1001 |
1175 EXPECT_TRUE(result1->IsCompleted()); | 1002 // Complete all the requests (in some order). |
1176 EXPECT_EQ(net::OK, result1->GetResultCode()); | 1003 // Note that as we complete requests, they shift up in |pending_requests()|. |
1177 EXPECT_EQ("pac-v1.request1:80", | |
1178 result1->GetProxyInfo().proxy_server().ToURI()); | |
1179 | 1004 |
1180 EXPECT_TRUE(result2->IsCompleted()); | 1005 resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80"); |
1181 EXPECT_EQ(net::OK, result2->GetResultCode()); | 1006 resolver->pending_requests()[2]->CompleteNow(net::OK); |
1182 EXPECT_EQ("pac-v1.request2:80", | |
1183 result2->GetProxyInfo().proxy_server().ToURI()); | |
1184 | 1007 |
1185 EXPECT_TRUE(result3->IsCompleted()); | 1008 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); |
1186 EXPECT_EQ(net::OK, result3->GetResultCode()); | 1009 resolver->pending_requests()[0]->CompleteNow(net::OK); |
1187 EXPECT_EQ("pac-v1.request3:80", | 1010 |
1188 result3->GetProxyInfo().proxy_server().ToURI()); | 1011 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); |
| 1012 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 1013 |
| 1014 // Complete and verify that requests ran as expected. |
| 1015 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 1016 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); |
| 1017 |
| 1018 EXPECT_EQ(net::OK, callback2.WaitForResult()); |
| 1019 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); |
| 1020 |
| 1021 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
| 1022 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); |
1189 } | 1023 } |
1190 | 1024 |
1191 // Test cancellation of a request, while the PAC script is being fetched. | 1025 // Test cancellation of a request, while the PAC script is being fetched. |
1192 TEST(ProxyServiceTest, CancelWhilePACFetching) { | 1026 TEST(ProxyServiceTest, CancelWhilePACFetching) { |
1193 MockProxyConfigService* config_service = | 1027 MockProxyConfigService* config_service = |
1194 new MockProxyConfigService("http://foopy/proxy.pac"); | 1028 new MockProxyConfigService("http://foopy/proxy.pac"); |
1195 | 1029 |
1196 MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; | 1030 MockAsyncProxyResolverExpectsBytes* resolver = |
| 1031 new MockAsyncProxyResolverExpectsBytes; |
1197 | 1032 |
1198 ProxyServiceWithFutures service(config_service, resolver); | 1033 net::ProxyService service(config_service, resolver); |
1199 | 1034 |
1200 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | 1035 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; |
1201 service.SetProxyScriptFetcher(fetcher); | 1036 service.SetProxyScriptFetcher(fetcher); |
1202 | 1037 |
1203 // Start 3 requests. | 1038 // Start 3 requests. |
1204 scoped_refptr<ResultFuture> result1; | 1039 net::ProxyInfo info1; |
1205 service.ResolveProxy(&result1, GURL("http://request1")); | 1040 TestCompletionCallback callback1; |
| 1041 net::ProxyService::PacRequest* request1; |
| 1042 int rv = service.ResolveProxy( |
| 1043 GURL("http://request1"), &info1, &callback1, &request1); |
| 1044 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
1206 | 1045 |
1207 scoped_refptr<ResultFuture> result2; | 1046 // The first request should have triggered download of PAC script. |
1208 service.ResolveProxy(&result2, GURL("http://request2")); | 1047 EXPECT_TRUE(fetcher->has_pending_request()); |
| 1048 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); |
1209 | 1049 |
1210 scoped_refptr<ResultFuture> result3; | 1050 net::ProxyInfo info2; |
1211 service.ResolveProxy(&result3, GURL("http://request3")); | 1051 TestCompletionCallback callback2; |
| 1052 net::ProxyService::PacRequest* request2; |
| 1053 rv = service.ResolveProxy( |
| 1054 GURL("http://request2"), &info2, &callback2, &request2); |
| 1055 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1056 |
| 1057 net::ProxyInfo info3; |
| 1058 TestCompletionCallback callback3; |
| 1059 rv = service.ResolveProxy( |
| 1060 GURL("http://request3"), &info3, &callback3, NULL); |
| 1061 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1062 |
| 1063 // Nothing has been sent to the resolver yet. |
| 1064 EXPECT_TRUE(resolver->pending_requests().empty()); |
1212 | 1065 |
1213 // Cancel the first 2 requests. | 1066 // Cancel the first 2 requests. |
1214 result1->Cancel(); | 1067 service.CancelPacRequest(request1); |
1215 result2->Cancel(); | 1068 service.CancelPacRequest(request2); |
1216 | 1069 |
1217 // At this point the ProxyService should be waiting for the | 1070 // At this point the ProxyService should be waiting for the |
1218 // ProxyScriptFetcher to invoke its completion callback, notifying it of | 1071 // ProxyScriptFetcher to invoke its completion callback, notifying it of |
1219 // PAC script download completion. | 1072 // PAC script download completion. |
1220 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); | 1073 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); |
1221 | 1074 |
| 1075 // Now that the PAC script is downloaded, everything should have been sent |
| 1076 // over to the proxy resolver. |
| 1077 EXPECT_EQ("pac-v1", resolver->pac_bytes()); |
| 1078 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 1079 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url()); |
| 1080 |
1222 // Complete all the requests. | 1081 // Complete all the requests. |
1223 result3->WaitUntilCompleted(); | 1082 resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80"); |
| 1083 resolver->pending_requests()[0]->CompleteNow(net::OK); |
1224 | 1084 |
1225 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. | 1085 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
1226 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. | 1086 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); |
1227 | 1087 |
1228 EXPECT_TRUE(result3->IsCompleted()); | 1088 EXPECT_TRUE(resolver->cancelled_requests().empty()); |
1229 EXPECT_EQ(net::OK, result3->GetResultCode()); | 1089 |
1230 EXPECT_EQ("pac-v1.request3:80", | 1090 EXPECT_FALSE(callback1.have_result()); // Cancelled. |
1231 result3->GetProxyInfo().proxy_server().ToURI()); | 1091 EXPECT_FALSE(callback2.have_result()); // Cancelled. |
1232 } | 1092 } |
1233 | 1093 |
1234 TEST(ProxyServiceTest, ResetProxyConfigService) { | 1094 TEST(ProxyServiceTest, ResetProxyConfigService) { |
1235 net::ProxyConfig config1; | 1095 net::ProxyConfig config1; |
1236 config1.proxy_rules.ParseFromString("foopy1:8080"); | 1096 config1.proxy_rules.ParseFromString("foopy1:8080"); |
1237 config1.auto_detect = false; | 1097 config1.auto_detect = false; |
1238 scoped_ptr<SyncProxyService> service( | 1098 net::ProxyService service(new MockProxyConfigService(config1), |
1239 new SyncProxyService(new MockProxyConfigService(config1), | 1099 new MockAsyncProxyResolverExpectsBytes); |
1240 new MockProxyResolverWithoutFetch)); | |
1241 | 1100 |
1242 net::ProxyInfo info; | 1101 net::ProxyInfo info; |
1243 service->ResolveProxy(GURL("http://request1"), &info); | 1102 TestCompletionCallback callback1; |
| 1103 int rv = service.ResolveProxy( |
| 1104 GURL("http://request1"), &info, &callback1, NULL); |
| 1105 EXPECT_EQ(net::OK, rv); |
1244 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 1106 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
1245 | 1107 |
1246 net::ProxyConfig config2; | 1108 net::ProxyConfig config2; |
1247 config2.proxy_rules.ParseFromString("foopy2:8080"); | 1109 config2.proxy_rules.ParseFromString("foopy2:8080"); |
1248 config2.auto_detect = false; | 1110 config2.auto_detect = false; |
1249 int result = service->ResetConfigService(new MockProxyConfigService(config2)); | 1111 service.ResetConfigService(new MockProxyConfigService(config2)); |
1250 DCHECK(result == 0); | 1112 TestCompletionCallback callback2; |
1251 service->ResolveProxy(GURL("http://request2"), &info); | 1113 rv = service.ResolveProxy(GURL("http://request2"), &info, &callback2, NULL); |
| 1114 EXPECT_EQ(net::OK, rv); |
1252 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); | 1115 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); |
1253 } | 1116 } |
OLD | NEW |