Probably broke Win7 Tests (dbg)(6). http://build.chromium.org/p/chromium.win/builders...
[chromium-blink-merge.git] / net / proxy / proxy_service_unittest.cc
blob69ab4ce050ffd8ee20021afed5347b0c7ec2dea2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/proxy/proxy_service.h"
7 #include <vector>
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "net/base/load_flags.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/net_log.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/network_delegate.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/proxy/dhcp_proxy_script_fetcher.h"
20 #include "net/proxy/mock_proxy_resolver.h"
21 #include "net/proxy/mock_proxy_script_fetcher.h"
22 #include "net/proxy/proxy_config_service.h"
23 #include "net/proxy/proxy_resolver.h"
24 #include "net/proxy/proxy_script_fetcher.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "url/gurl.h"
28 using base::ASCIIToUTF16;
30 // TODO(eroman): Write a test which exercises
31 // ProxyService::SuspendAllPendingRequests().
32 namespace net {
33 namespace {
35 // This polling policy will decide to poll every 1 ms.
36 class ImmediatePollPolicy : public ProxyService::PacPollPolicy {
37 public:
38 ImmediatePollPolicy() {}
40 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
41 base::TimeDelta* next_delay) const OVERRIDE {
42 *next_delay = base::TimeDelta::FromMilliseconds(1);
43 return MODE_USE_TIMER;
46 private:
47 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy);
50 // This polling policy chooses a fantastically large delay. In other words, it
51 // will never trigger a poll
52 class NeverPollPolicy : public ProxyService::PacPollPolicy {
53 public:
54 NeverPollPolicy() {}
56 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
57 base::TimeDelta* next_delay) const OVERRIDE {
58 *next_delay = base::TimeDelta::FromDays(60);
59 return MODE_USE_TIMER;
62 private:
63 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy);
66 // This polling policy starts a poll immediately after network activity.
67 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
68 public:
69 ImmediateAfterActivityPollPolicy() {}
71 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
72 base::TimeDelta* next_delay) const OVERRIDE {
73 *next_delay = base::TimeDelta();
74 return MODE_START_AFTER_ACTIVITY;
77 private:
78 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy);
81 // This test fixture is used to partially disable the background polling done by
82 // the ProxyService (which it uses to detect whenever its PAC script contents or
83 // WPAD results have changed).
85 // We disable the feature by setting the poll interval to something really
86 // large, so it will never actually be reached even on the slowest bots that run
87 // these tests.
89 // We disable the polling in order to avoid any timing dependencies in the
90 // tests. If the bot were to run the tests very slowly and we hadn't disabled
91 // polling, then it might start a background re-try in the middle of our test
92 // and confuse our expectations leading to flaky failures.
94 // The tests which verify the polling code re-enable the polling behavior but
95 // are careful to avoid timing problems.
96 class ProxyServiceTest : public testing::Test {
97 protected:
98 virtual void SetUp() OVERRIDE {
99 testing::Test::SetUp();
100 previous_policy_ =
101 ProxyService::set_pac_script_poll_policy(&never_poll_policy_);
104 virtual void TearDown() OVERRIDE {
105 // Restore the original policy.
106 ProxyService::set_pac_script_poll_policy(previous_policy_);
107 testing::Test::TearDown();
110 private:
111 NeverPollPolicy never_poll_policy_;
112 const ProxyService::PacPollPolicy* previous_policy_;
115 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
116 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
118 class MockProxyConfigService: public ProxyConfigService {
119 public:
120 explicit MockProxyConfigService(const ProxyConfig& config)
121 : availability_(CONFIG_VALID),
122 config_(config) {
125 explicit MockProxyConfigService(const std::string& pac_url)
126 : availability_(CONFIG_VALID),
127 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) {
130 virtual void AddObserver(Observer* observer) OVERRIDE {
131 observers_.AddObserver(observer);
134 virtual void RemoveObserver(Observer* observer) OVERRIDE {
135 observers_.RemoveObserver(observer);
138 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* results)
139 OVERRIDE {
140 if (availability_ == CONFIG_VALID)
141 *results = config_;
142 return availability_;
145 void SetConfig(const ProxyConfig& config) {
146 availability_ = CONFIG_VALID;
147 config_ = config;
148 FOR_EACH_OBSERVER(Observer, observers_,
149 OnProxyConfigChanged(config_, availability_));
152 private:
153 ConfigAvailability availability_;
154 ProxyConfig config_;
155 ObserverList<Observer, true> observers_;
158 // A test network delegate that exercises the OnResolveProxy callback.
159 class TestResolveProxyNetworkDelegate : public NetworkDelegate {
160 public:
161 TestResolveProxyNetworkDelegate()
162 : on_resolve_proxy_called_(false),
163 add_proxy_(false),
164 remove_proxy_(false) {
167 virtual void OnResolveProxy(
168 const GURL& url, int load_flags, ProxyInfo* result) OVERRIDE {
169 on_resolve_proxy_called_ = true;
170 DCHECK(!add_proxy_ || !remove_proxy_);
171 if (add_proxy_) {
172 result->UseNamedProxy("delegate_proxy.com");
173 } else if (remove_proxy_) {
174 result->UseDirect();
178 bool on_resolve_proxy_called() const {
179 return on_resolve_proxy_called_;
182 void set_add_proxy(bool add_proxy) {
183 add_proxy_ = add_proxy;
186 void set_remove_proxy(bool remove_proxy) {
187 remove_proxy_ = remove_proxy;
190 private:
191 bool on_resolve_proxy_called_;
192 bool add_proxy_;
193 bool remove_proxy_;
196 } // namespace
198 TEST_F(ProxyServiceTest, Direct) {
199 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
200 ProxyService service(new MockProxyConfigService(
201 ProxyConfig::CreateDirect()), resolver, NULL);
203 GURL url("http://www.google.com/");
205 ProxyInfo info;
206 TestCompletionCallback callback;
207 CapturingBoundNetLog log;
208 int rv = service.ResolveProxy(
209 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
210 log.bound());
211 EXPECT_EQ(OK, rv);
212 EXPECT_TRUE(resolver->pending_requests().empty());
214 EXPECT_TRUE(info.is_direct());
215 EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
216 EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
218 // Check the NetLog was filled correctly.
219 CapturingNetLog::CapturedEntryList entries;
220 log.GetEntries(&entries);
222 EXPECT_EQ(3u, entries.size());
223 EXPECT_TRUE(LogContainsBeginEvent(
224 entries, 0, NetLog::TYPE_PROXY_SERVICE));
225 EXPECT_TRUE(LogContainsEvent(
226 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
227 NetLog::PHASE_NONE));
228 EXPECT_TRUE(LogContainsEndEvent(
229 entries, 2, NetLog::TYPE_PROXY_SERVICE));
232 TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) {
233 ProxyConfig config;
234 config.proxy_rules().ParseFromString("foopy1:8080");
235 config.set_auto_detect(false);
236 config.proxy_rules().bypass_rules.ParseFromString("*.org");
238 ProxyService service(
239 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
241 GURL url("http://www.google.com/");
242 GURL bypass_url("http://internet.org");
244 ProxyInfo info;
245 TestCompletionCallback callback;
246 CapturingBoundNetLog log;
248 // First, warm up the ProxyService.
249 int rv = service.ResolveProxy(
250 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
251 log.bound());
252 EXPECT_EQ(OK, rv);
254 // Verify that network delegate is invoked.
255 TestResolveProxyNetworkDelegate delegate;
256 rv = service.ResolveProxy(
257 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
258 log.bound());
259 EXPECT_TRUE(delegate.on_resolve_proxy_called());
261 // Verify that the NetworkDelegate's behavior is stateless across
262 // invocations of ResolveProxy. Start by having the callback add a proxy
263 // and checking that subsequent requests are not affected.
264 delegate.set_add_proxy(true);
266 // Callback should interpose:
267 rv = service.ResolveProxy(
268 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
269 log.bound());
270 EXPECT_FALSE(info.is_direct());
271 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com");
272 delegate.set_add_proxy(false);
274 // Check non-bypassed URL:
275 rv = service.ResolveProxy(
276 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
277 log.bound());
278 EXPECT_FALSE(info.is_direct());
279 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
281 // Check bypassed URL:
282 rv = service.ResolveProxy(
283 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL,
284 &delegate, log.bound());
285 EXPECT_TRUE(info.is_direct());
288 TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
289 // Same as OnResolveProxyCallbackAddProxy, but verify that the
290 // NetworkDelegate's behavior is stateless across invocations after it
291 // *removes* a proxy.
292 ProxyConfig config;
293 config.proxy_rules().ParseFromString("foopy1:8080");
294 config.set_auto_detect(false);
295 config.proxy_rules().bypass_rules.ParseFromString("*.org");
297 ProxyService service(
298 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
300 GURL url("http://www.google.com/");
301 GURL bypass_url("http://internet.org");
303 ProxyInfo info;
304 TestCompletionCallback callback;
305 CapturingBoundNetLog log;
307 // First, warm up the ProxyService.
308 int rv = service.ResolveProxy(
309 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
310 log.bound());
311 EXPECT_EQ(OK, rv);
313 TestResolveProxyNetworkDelegate delegate;
314 delegate.set_remove_proxy(true);
316 // Callback should interpose:
317 rv = service.ResolveProxy(
318 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
319 log.bound());
320 EXPECT_TRUE(info.is_direct());
321 delegate.set_remove_proxy(false);
323 // Check non-bypassed URL:
324 rv = service.ResolveProxy(
325 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
326 log.bound());
327 EXPECT_FALSE(info.is_direct());
328 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
330 // Check bypassed URL:
331 rv = service.ResolveProxy(
332 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL,
333 &delegate, log.bound());
334 EXPECT_TRUE(info.is_direct());
337 TEST_F(ProxyServiceTest, PAC) {
338 MockProxyConfigService* config_service =
339 new MockProxyConfigService("http://foopy/proxy.pac");
341 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
343 ProxyService service(config_service, resolver, NULL);
345 GURL url("http://www.google.com/");
347 ProxyInfo info;
348 TestCompletionCallback callback;
349 ProxyService::PacRequest* request;
350 CapturingBoundNetLog log;
352 int rv = service.ResolveProxy(
353 url, net::LOAD_NORMAL, &info, callback.callback(), &request, NULL,
354 log.bound());
355 EXPECT_EQ(ERR_IO_PENDING, rv);
357 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request));
359 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
360 resolver->pending_set_pac_script_request()->script_data()->url());
361 resolver->pending_set_pac_script_request()->CompleteNow(OK);
363 ASSERT_EQ(1u, resolver->pending_requests().size());
364 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
366 // Set the result in proxy resolver.
367 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
368 resolver->pending_requests()[0]->CompleteNow(OK);
370 EXPECT_EQ(OK, callback.WaitForResult());
371 EXPECT_FALSE(info.is_direct());
372 EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
373 EXPECT_TRUE(info.did_use_pac_script());
375 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
376 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
377 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
379 // Check the NetLog was filled correctly.
380 CapturingNetLog::CapturedEntryList entries;
381 log.GetEntries(&entries);
383 EXPECT_EQ(5u, entries.size());
384 EXPECT_TRUE(LogContainsBeginEvent(
385 entries, 0, NetLog::TYPE_PROXY_SERVICE));
386 EXPECT_TRUE(LogContainsBeginEvent(
387 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
388 EXPECT_TRUE(LogContainsEndEvent(
389 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
390 EXPECT_TRUE(LogContainsEndEvent(
391 entries, 4, NetLog::TYPE_PROXY_SERVICE));
394 // Test that the proxy resolver does not see the URL's username/password
395 // or its reference section.
396 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) {
397 MockProxyConfigService* config_service =
398 new MockProxyConfigService("http://foopy/proxy.pac");
400 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
402 ProxyService service(config_service, resolver, NULL);
404 GURL url("http://username:password@www.google.com/?ref#hash#hash");
406 ProxyInfo info;
407 TestCompletionCallback callback;
408 int rv = service.ResolveProxy(
409 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
410 BoundNetLog());
411 EXPECT_EQ(ERR_IO_PENDING, rv);
413 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
414 resolver->pending_set_pac_script_request()->script_data()->url());
415 resolver->pending_set_pac_script_request()->CompleteNow(OK);
417 ASSERT_EQ(1u, resolver->pending_requests().size());
418 // The URL should have been simplified, stripping the username/password/hash.
419 EXPECT_EQ(GURL("http://www.google.com/?ref"),
420 resolver->pending_requests()[0]->url());
422 // We end here without ever completing the request -- destruction of
423 // ProxyService will cancel the outstanding request.
426 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
427 MockProxyConfigService* config_service =
428 new MockProxyConfigService("http://foopy/proxy.pac");
429 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
431 ProxyService service(config_service, resolver, NULL);
433 GURL url("http://www.google.com/");
435 ProxyInfo info;
436 TestCompletionCallback callback1;
437 int rv = service.ResolveProxy(
438 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
439 BoundNetLog());
440 EXPECT_EQ(ERR_IO_PENDING, rv);
442 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
443 resolver->pending_set_pac_script_request()->script_data()->url());
444 resolver->pending_set_pac_script_request()->CompleteNow(OK);
446 ASSERT_EQ(1u, resolver->pending_requests().size());
447 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
449 // Set the result in proxy resolver.
450 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
451 resolver->pending_requests()[0]->CompleteNow(OK);
453 EXPECT_EQ(OK, callback1.WaitForResult());
454 EXPECT_FALSE(info.is_direct());
455 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
456 EXPECT_TRUE(info.did_use_pac_script());
458 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
459 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
460 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
462 // Now, imagine that connecting to foopy:8080 fails: there is nothing
463 // left to fallback to, since our proxy list was NOT terminated by
464 // DIRECT.
465 TestCompletionCallback callback2;
466 rv = service.ReconsiderProxyAfterError(
467 url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED,
468 &info, callback2.callback(), NULL, NULL, BoundNetLog());
469 // ReconsiderProxyAfterError returns error indicating nothing left.
470 EXPECT_EQ(ERR_FAILED, rv);
471 EXPECT_TRUE(info.is_empty());
474 // Test that if the execution of the PAC script fails (i.e. javascript runtime
475 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
476 TEST_F(ProxyServiceTest, PAC_RuntimeError) {
477 MockProxyConfigService* config_service =
478 new MockProxyConfigService("http://foopy/proxy.pac");
479 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
481 ProxyService service(config_service, resolver, NULL);
483 GURL url("http://this-causes-js-error/");
485 ProxyInfo info;
486 TestCompletionCallback callback1;
487 int rv = service.ResolveProxy(
488 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
489 BoundNetLog());
490 EXPECT_EQ(ERR_IO_PENDING, rv);
492 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
493 resolver->pending_set_pac_script_request()->script_data()->url());
494 resolver->pending_set_pac_script_request()->CompleteNow(OK);
496 ASSERT_EQ(1u, resolver->pending_requests().size());
497 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
499 // Simulate a failure in the PAC executor.
500 resolver->pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
502 EXPECT_EQ(OK, callback1.WaitForResult());
504 // Since the PAC script was non-mandatory, we should have fallen-back to
505 // DIRECT.
506 EXPECT_TRUE(info.is_direct());
507 EXPECT_TRUE(info.did_use_pac_script());
508 EXPECT_EQ(1, info.config_id());
510 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
511 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
512 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
515 // The proxy list could potentially contain the DIRECT fallback choice
516 // in a location other than the very end of the list, and could even
517 // specify it multiple times.
519 // This is not a typical usage, but we will obey it.
520 // (If we wanted to disallow this type of input, the right place to
521 // enforce it would be in parsing the PAC result string).
523 // This test will use the PAC result string:
525 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
527 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
528 // then foobar:20, and then give up and error.
530 // The important check of this test is to make sure that DIRECT is not somehow
531 // cached as being a bad proxy.
532 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
533 MockProxyConfigService* config_service =
534 new MockProxyConfigService("http://foopy/proxy.pac");
535 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
537 ProxyService service(config_service, resolver, NULL);
539 GURL url("http://www.google.com/");
541 ProxyInfo info;
542 TestCompletionCallback callback1;
543 int rv = service.ResolveProxy(
544 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
545 BoundNetLog());
546 EXPECT_EQ(ERR_IO_PENDING, rv);
548 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
549 resolver->pending_set_pac_script_request()->script_data()->url());
550 resolver->pending_set_pac_script_request()->CompleteNow(OK);
552 ASSERT_EQ(1u, resolver->pending_requests().size());
553 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
555 // Set the result in proxy resolver.
556 resolver->pending_requests()[0]->results()->UsePacString(
557 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
558 resolver->pending_requests()[0]->CompleteNow(OK);
560 EXPECT_EQ(OK, callback1.WaitForResult());
561 EXPECT_TRUE(info.is_direct());
563 // Fallback 1.
564 TestCompletionCallback callback2;
565 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
566 net::ERR_PROXY_CONNECTION_FAILED,
567 &info, callback2.callback(), NULL,
568 NULL, BoundNetLog());
569 EXPECT_EQ(OK, rv);
570 EXPECT_FALSE(info.is_direct());
571 EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
573 // Fallback 2.
574 TestCompletionCallback callback3;
575 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
576 net::ERR_PROXY_CONNECTION_FAILED,
577 &info, callback3.callback(), NULL,
578 NULL, BoundNetLog());
579 EXPECT_EQ(OK, rv);
580 EXPECT_TRUE(info.is_direct());
582 // Fallback 3.
583 TestCompletionCallback callback4;
584 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
585 net::ERR_PROXY_CONNECTION_FAILED,
586 &info, callback4.callback(), NULL,
587 NULL, BoundNetLog());
588 EXPECT_EQ(OK, rv);
589 EXPECT_FALSE(info.is_direct());
590 EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
592 // Fallback 4 -- Nothing to fall back to!
593 TestCompletionCallback callback5;
594 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
595 net::ERR_PROXY_CONNECTION_FAILED,
596 &info, callback5.callback(), NULL,
597 NULL, BoundNetLog());
598 EXPECT_EQ(ERR_FAILED, rv);
599 EXPECT_TRUE(info.is_empty());
602 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
603 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
604 // to ProxyInfo after the proxy is resolved via a PAC script.
605 ProxyConfig config =
606 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
607 config.set_source(PROXY_CONFIG_SOURCE_TEST);
609 MockProxyConfigService* config_service = new MockProxyConfigService(config);
610 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
611 ProxyService service(config_service, resolver, NULL);
613 // Resolve something.
614 GURL url("http://www.google.com/");
615 ProxyInfo info;
616 TestCompletionCallback callback;
617 int rv = service.ResolveProxy(
618 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
619 BoundNetLog());
620 ASSERT_EQ(ERR_IO_PENDING, rv);
621 resolver->pending_set_pac_script_request()->CompleteNow(OK);
622 ASSERT_EQ(1u, resolver->pending_requests().size());
624 // Set the result in proxy resolver.
625 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
626 resolver->pending_requests()[0]->CompleteNow(OK);
628 EXPECT_EQ(OK, callback.WaitForResult());
629 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
630 EXPECT_TRUE(info.did_use_pac_script());
632 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
633 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
634 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
637 TEST_F(ProxyServiceTest, ProxyResolverFails) {
638 // Test what happens when the ProxyResolver fails. The download and setting
639 // of the PAC script have already succeeded, so this corresponds with a
640 // javascript runtime error while calling FindProxyForURL().
642 MockProxyConfigService* config_service =
643 new MockProxyConfigService("http://foopy/proxy.pac");
645 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
647 ProxyService service(config_service, resolver, NULL);
649 // Start first resolve request.
650 GURL url("http://www.google.com/");
651 ProxyInfo info;
652 TestCompletionCallback callback1;
653 int rv = service.ResolveProxy(
654 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
655 BoundNetLog());
656 EXPECT_EQ(ERR_IO_PENDING, rv);
658 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
659 resolver->pending_set_pac_script_request()->script_data()->url());
660 resolver->pending_set_pac_script_request()->CompleteNow(OK);
662 ASSERT_EQ(1u, resolver->pending_requests().size());
663 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
665 // Fail the first resolve request in MockAsyncProxyResolver.
666 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
668 // Although the proxy resolver failed the request, ProxyService implicitly
669 // falls-back to DIRECT.
670 EXPECT_EQ(OK, callback1.WaitForResult());
671 EXPECT_TRUE(info.is_direct());
673 // Failed PAC executions still have proxy resolution times.
674 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
675 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
676 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
678 // The second resolve request will try to run through the proxy resolver,
679 // regardless of whether the first request failed in it.
680 TestCompletionCallback callback2;
681 rv = service.ResolveProxy(
682 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL,
683 BoundNetLog());
684 EXPECT_EQ(ERR_IO_PENDING, rv);
686 ASSERT_EQ(1u, resolver->pending_requests().size());
687 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
689 // This time we will have the resolver succeed (perhaps the PAC script has
690 // a dependency on the current time).
691 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
692 resolver->pending_requests()[0]->CompleteNow(OK);
694 EXPECT_EQ(OK, callback2.WaitForResult());
695 EXPECT_FALSE(info.is_direct());
696 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
699 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
700 // Test what happens when the ProxyScriptResolver fails to download a
701 // mandatory PAC script.
703 ProxyConfig config(
704 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
705 config.set_pac_mandatory(true);
707 MockProxyConfigService* config_service = new MockProxyConfigService(config);
709 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
711 ProxyService service(config_service, resolver, NULL);
713 // Start first resolve request.
714 GURL url("http://www.google.com/");
715 ProxyInfo info;
716 TestCompletionCallback callback1;
717 int rv = service.ResolveProxy(
718 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
719 BoundNetLog());
720 EXPECT_EQ(ERR_IO_PENDING, rv);
722 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
723 resolver->pending_set_pac_script_request()->script_data()->url());
724 resolver->pending_set_pac_script_request()->CompleteNow(ERR_FAILED);
726 ASSERT_EQ(0u, resolver->pending_requests().size());
728 // As the proxy resolver failed the request and is configured for a mandatory
729 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
730 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
731 callback1.WaitForResult());
732 EXPECT_FALSE(info.is_direct());
734 // As the proxy resolver failed the request and is configured for a mandatory
735 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
736 TestCompletionCallback callback2;
737 rv = service.ResolveProxy(
738 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL,
739 BoundNetLog());
740 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
741 EXPECT_FALSE(info.is_direct());
744 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
745 // Test what happens when the ProxyResolver fails that is configured to use a
746 // mandatory PAC script. The download of the PAC script has already
747 // succeeded but the PAC script contains no valid javascript.
749 ProxyConfig config(
750 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
751 config.set_pac_mandatory(true);
753 MockProxyConfigService* config_service = new MockProxyConfigService(config);
755 MockAsyncProxyResolverExpectsBytes* resolver =
756 new MockAsyncProxyResolverExpectsBytes;
758 ProxyService service(config_service, resolver, NULL);
760 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
761 DhcpProxyScriptFetcher* dhcp_fetcher = new DoNothingDhcpProxyScriptFetcher();
762 service.SetProxyScriptFetchers(fetcher, dhcp_fetcher);
764 // Start resolve request.
765 GURL url("http://www.google.com/");
766 ProxyInfo info;
767 TestCompletionCallback callback;
768 int rv = service.ResolveProxy(
769 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
770 BoundNetLog());
771 EXPECT_EQ(ERR_IO_PENDING, rv);
773 // Check that nothing has been sent to the proxy resolver yet.
774 ASSERT_EQ(0u, resolver->pending_requests().size());
776 // Downloading the PAC script succeeds.
777 EXPECT_TRUE(fetcher->has_pending_request());
778 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
779 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
781 EXPECT_FALSE(fetcher->has_pending_request());
782 ASSERT_EQ(0u, resolver->pending_requests().size());
784 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
785 // mandatory for this configuration, the ProxyService must not implicitly
786 // fall-back to DIRECT.
787 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
788 callback.WaitForResult());
789 EXPECT_FALSE(info.is_direct());
792 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
793 // Test what happens when the ProxyResolver fails that is configured to use a
794 // mandatory PAC script. The download and setting of the PAC script have
795 // already succeeded, so this corresponds with a javascript runtime error
796 // while calling FindProxyForURL().
798 ProxyConfig config(
799 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
800 config.set_pac_mandatory(true);
802 MockProxyConfigService* config_service = new MockProxyConfigService(config);
804 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
806 ProxyService service(config_service, resolver, NULL);
808 // Start first resolve request.
809 GURL url("http://www.google.com/");
810 ProxyInfo info;
811 TestCompletionCallback callback1;
812 int rv = service.ResolveProxy(
813 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
814 BoundNetLog());
815 EXPECT_EQ(ERR_IO_PENDING, rv);
817 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
818 resolver->pending_set_pac_script_request()->script_data()->url());
819 resolver->pending_set_pac_script_request()->CompleteNow(OK);
821 ASSERT_EQ(1u, resolver->pending_requests().size());
822 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
824 // Fail the first resolve request in MockAsyncProxyResolver.
825 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
827 // As the proxy resolver failed the request and is configured for a mandatory
828 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
829 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
830 callback1.WaitForResult());
831 EXPECT_FALSE(info.is_direct());
833 // The second resolve request will try to run through the proxy resolver,
834 // regardless of whether the first request failed in it.
835 TestCompletionCallback callback2;
836 rv = service.ResolveProxy(
837 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL,
838 BoundNetLog());
839 EXPECT_EQ(ERR_IO_PENDING, rv);
841 ASSERT_EQ(1u, resolver->pending_requests().size());
842 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
844 // This time we will have the resolver succeed (perhaps the PAC script has
845 // a dependency on the current time).
846 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
847 resolver->pending_requests()[0]->CompleteNow(OK);
849 EXPECT_EQ(OK, callback2.WaitForResult());
850 EXPECT_FALSE(info.is_direct());
851 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
854 TEST_F(ProxyServiceTest, ProxyFallback) {
855 // Test what happens when we specify multiple proxy servers and some of them
856 // are bad.
858 MockProxyConfigService* config_service =
859 new MockProxyConfigService("http://foopy/proxy.pac");
861 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
863 ProxyService service(config_service, resolver, NULL);
865 GURL url("http://www.google.com/");
867 // Get the proxy information.
868 ProxyInfo info;
869 TestCompletionCallback callback1;
870 int rv = service.ResolveProxy(
871 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
872 BoundNetLog());
873 EXPECT_EQ(ERR_IO_PENDING, rv);
875 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
876 resolver->pending_set_pac_script_request()->script_data()->url());
877 resolver->pending_set_pac_script_request()->CompleteNow(OK);
879 ASSERT_EQ(1u, resolver->pending_requests().size());
880 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
882 // Set the result in proxy resolver.
883 resolver->pending_requests()[0]->results()->UseNamedProxy(
884 "foopy1:8080;foopy2:9090");
885 resolver->pending_requests()[0]->CompleteNow(OK);
887 // The first item is valid.
888 EXPECT_EQ(OK, callback1.WaitForResult());
889 EXPECT_FALSE(info.is_direct());
890 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
892 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
893 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
894 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
895 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
896 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
898 // Fake an error on the proxy.
899 TestCompletionCallback callback2;
900 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
901 net::ERR_PROXY_CONNECTION_FAILED,
902 &info, callback2.callback(), NULL,
903 NULL, BoundNetLog());
904 EXPECT_EQ(OK, rv);
906 // Proxy times should not have been modified by fallback.
907 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
908 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
910 // The second proxy should be specified.
911 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
912 // Report back that the second proxy worked. This will globally mark the
913 // first proxy as bad.
914 service.ReportSuccess(info);
916 TestCompletionCallback callback3;
917 rv = service.ResolveProxy(
918 url, net::LOAD_NORMAL, &info, callback3.callback(), NULL, NULL,
919 BoundNetLog());
920 EXPECT_EQ(ERR_IO_PENDING, rv);
922 ASSERT_EQ(1u, resolver->pending_requests().size());
923 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
925 // Set the result in proxy resolver -- the second result is already known
926 // to be bad, so we will not try to use it initially.
927 resolver->pending_requests()[0]->results()->UseNamedProxy(
928 "foopy3:7070;foopy1:8080;foopy2:9090");
929 resolver->pending_requests()[0]->CompleteNow(OK);
931 EXPECT_EQ(OK, callback3.WaitForResult());
932 EXPECT_FALSE(info.is_direct());
933 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
935 // Proxy times should have been updated, so get them again.
936 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
937 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
938 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
939 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
940 proxy_resolve_start_time = info.proxy_resolve_start_time();
941 proxy_resolve_end_time = info.proxy_resolve_end_time();
943 // We fake another error. It should now try the third one.
944 TestCompletionCallback callback4;
945 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
946 net::ERR_PROXY_CONNECTION_FAILED,
947 &info, callback4.callback(), NULL,
948 NULL, BoundNetLog());
949 EXPECT_EQ(OK, rv);
950 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
952 // We fake another error. At this point we have tried all of the
953 // proxy servers we thought were valid; next we try the proxy server
954 // that was in our bad proxies map (foopy1:8080).
955 TestCompletionCallback callback5;
956 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
957 net::ERR_PROXY_CONNECTION_FAILED,
958 &info, callback5.callback(), NULL,
959 NULL, BoundNetLog());
960 EXPECT_EQ(OK, rv);
961 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
963 // Fake another error, the last proxy is gone, the list should now be empty,
964 // so there is nothing left to try.
965 TestCompletionCallback callback6;
966 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
967 net::ERR_PROXY_CONNECTION_FAILED,
968 &info, callback6.callback(), NULL,
969 NULL, BoundNetLog());
970 EXPECT_EQ(ERR_FAILED, rv);
971 EXPECT_FALSE(info.is_direct());
972 EXPECT_TRUE(info.is_empty());
974 // Proxy times should not have been modified by fallback.
975 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
976 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
978 // Look up proxies again
979 TestCompletionCallback callback7;
980 rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback7.callback(),
981 NULL, NULL, BoundNetLog());
982 EXPECT_EQ(ERR_IO_PENDING, rv);
984 ASSERT_EQ(1u, resolver->pending_requests().size());
985 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
987 // This time, the first 3 results have been found to be bad, but only the
988 // first proxy has been confirmed ...
989 resolver->pending_requests()[0]->results()->UseNamedProxy(
990 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
991 resolver->pending_requests()[0]->CompleteNow(OK);
993 // ... therefore, we should see the second proxy first.
994 EXPECT_EQ(OK, callback7.WaitForResult());
995 EXPECT_FALSE(info.is_direct());
996 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
998 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
999 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1000 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1001 // TODO(nsylvain): Test that the proxy can be retried after the delay.
1004 // This test is similar to ProxyFallback, but this time we have an explicit
1005 // fallback choice to DIRECT.
1006 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
1007 MockProxyConfigService* config_service =
1008 new MockProxyConfigService("http://foopy/proxy.pac");
1010 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1012 ProxyService service(config_service, resolver, NULL);
1014 GURL url("http://www.google.com/");
1016 // Get the proxy information.
1017 ProxyInfo info;
1018 TestCompletionCallback callback1;
1019 int rv = service.ResolveProxy(
1020 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1021 BoundNetLog());
1022 EXPECT_EQ(ERR_IO_PENDING, rv);
1024 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1025 resolver->pending_set_pac_script_request()->script_data()->url());
1026 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1028 ASSERT_EQ(1u, resolver->pending_requests().size());
1029 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1031 // Set the result in proxy resolver.
1032 resolver->pending_requests()[0]->results()->UsePacString(
1033 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
1034 resolver->pending_requests()[0]->CompleteNow(OK);
1036 // Get the first result.
1037 EXPECT_EQ(OK, callback1.WaitForResult());
1038 EXPECT_FALSE(info.is_direct());
1039 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1041 // Fake an error on the proxy.
1042 TestCompletionCallback callback2;
1043 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1044 net::ERR_PROXY_CONNECTION_FAILED,
1045 &info, callback2.callback(), NULL,
1046 NULL, BoundNetLog());
1047 EXPECT_EQ(OK, rv);
1049 // Now we get back the second proxy.
1050 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1052 // Fake an error on this proxy as well.
1053 TestCompletionCallback callback3;
1054 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1055 net::ERR_PROXY_CONNECTION_FAILED,
1056 &info, callback3.callback(), NULL,
1057 NULL, BoundNetLog());
1058 EXPECT_EQ(OK, rv);
1060 // Finally, we get back DIRECT.
1061 EXPECT_TRUE(info.is_direct());
1063 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1064 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1065 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1067 // Now we tell the proxy service that even DIRECT failed.
1068 TestCompletionCallback callback4;
1069 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1070 net::ERR_PROXY_CONNECTION_FAILED,
1071 &info, callback4.callback(), NULL,
1072 NULL, BoundNetLog());
1073 // There was nothing left to try after DIRECT, so we are out of
1074 // choices.
1075 EXPECT_EQ(ERR_FAILED, rv);
1078 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
1079 // Test proxy failover when new settings are available.
1081 MockProxyConfigService* config_service =
1082 new MockProxyConfigService("http://foopy/proxy.pac");
1084 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1086 ProxyService service(config_service, resolver, NULL);
1088 GURL url("http://www.google.com/");
1090 // Get the proxy information.
1091 ProxyInfo info;
1092 TestCompletionCallback callback1;
1093 int rv = service.ResolveProxy(
1094 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1095 BoundNetLog());
1096 EXPECT_EQ(ERR_IO_PENDING, rv);
1098 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1099 resolver->pending_set_pac_script_request()->script_data()->url());
1100 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1102 ASSERT_EQ(1u, resolver->pending_requests().size());
1103 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1105 // Set the result in proxy resolver.
1106 resolver->pending_requests()[0]->results()->UseNamedProxy(
1107 "foopy1:8080;foopy2:9090");
1108 resolver->pending_requests()[0]->CompleteNow(OK);
1110 // The first item is valid.
1111 EXPECT_EQ(OK, callback1.WaitForResult());
1112 EXPECT_FALSE(info.is_direct());
1113 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1115 // Fake an error on the proxy, and also a new configuration on the proxy.
1116 config_service->SetConfig(
1117 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
1119 TestCompletionCallback callback2;
1120 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1121 net::ERR_PROXY_CONNECTION_FAILED,
1122 &info, callback2.callback(), NULL,
1123 NULL, BoundNetLog());
1124 EXPECT_EQ(ERR_IO_PENDING, rv);
1126 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
1127 resolver->pending_set_pac_script_request()->script_data()->url());
1128 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1130 ASSERT_EQ(1u, resolver->pending_requests().size());
1131 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1133 resolver->pending_requests()[0]->results()->UseNamedProxy(
1134 "foopy1:8080;foopy2:9090");
1135 resolver->pending_requests()[0]->CompleteNow(OK);
1137 // The first proxy is still there since the configuration changed.
1138 EXPECT_EQ(OK, callback2.WaitForResult());
1139 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1141 // We fake another error. It should now ignore the first one.
1142 TestCompletionCallback callback3;
1143 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1144 net::ERR_PROXY_CONNECTION_FAILED,
1145 &info, callback3.callback(), NULL,
1146 NULL, BoundNetLog());
1147 EXPECT_EQ(OK, rv);
1148 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1150 // We simulate a new configuration.
1151 config_service->SetConfig(
1152 ProxyConfig::CreateFromCustomPacURL(
1153 GURL("http://foopy-new2/proxy.pac")));
1155 // We fake another error. It should go back to the first proxy.
1156 TestCompletionCallback callback4;
1157 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1158 net::ERR_PROXY_CONNECTION_FAILED,
1159 &info, callback4.callback(), NULL,
1160 NULL, BoundNetLog());
1161 EXPECT_EQ(ERR_IO_PENDING, rv);
1163 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
1164 resolver->pending_set_pac_script_request()->script_data()->url());
1165 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1167 ASSERT_EQ(1u, resolver->pending_requests().size());
1168 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1170 resolver->pending_requests()[0]->results()->UseNamedProxy(
1171 "foopy1:8080;foopy2:9090");
1172 resolver->pending_requests()[0]->CompleteNow(OK);
1174 EXPECT_EQ(OK, callback4.WaitForResult());
1175 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1177 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1178 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1179 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1182 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
1183 // Test proxy failover when the configuration is bad.
1185 MockProxyConfigService* config_service =
1186 new MockProxyConfigService("http://foopy/proxy.pac");
1188 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1190 ProxyService service(config_service, resolver, NULL);
1192 GURL url("http://www.google.com/");
1194 // Get the proxy information.
1195 ProxyInfo info;
1196 TestCompletionCallback callback1;
1197 int rv = service.ResolveProxy(
1198 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1199 BoundNetLog());
1200 EXPECT_EQ(ERR_IO_PENDING, rv);
1202 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1203 resolver->pending_set_pac_script_request()->script_data()->url());
1204 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1205 ASSERT_EQ(1u, resolver->pending_requests().size());
1206 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1208 resolver->pending_requests()[0]->results()->UseNamedProxy(
1209 "foopy1:8080;foopy2:9090");
1210 resolver->pending_requests()[0]->CompleteNow(OK);
1212 // The first item is valid.
1213 EXPECT_EQ(OK, callback1.WaitForResult());
1214 EXPECT_FALSE(info.is_direct());
1215 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1217 // Fake a proxy error.
1218 TestCompletionCallback callback2;
1219 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1220 net::ERR_PROXY_CONNECTION_FAILED,
1221 &info, callback2.callback(), NULL,
1222 NULL, BoundNetLog());
1223 EXPECT_EQ(OK, rv);
1225 // The first proxy is ignored, and the second one is selected.
1226 EXPECT_FALSE(info.is_direct());
1227 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1229 // Fake a PAC failure.
1230 ProxyInfo info2;
1231 TestCompletionCallback callback3;
1232 rv = service.ResolveProxy(
1233 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL,
1234 BoundNetLog());
1235 EXPECT_EQ(ERR_IO_PENDING, rv);
1237 ASSERT_EQ(1u, resolver->pending_requests().size());
1238 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1240 // This simulates a javascript runtime error in the PAC script.
1241 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
1243 // Although the resolver failed, the ProxyService will implicitly fall-back
1244 // to a DIRECT connection.
1245 EXPECT_EQ(OK, callback3.WaitForResult());
1246 EXPECT_TRUE(info2.is_direct());
1247 EXPECT_FALSE(info2.is_empty());
1249 // The PAC script will work properly next time and successfully return a
1250 // proxy list. Since we have not marked the configuration as bad, it should
1251 // "just work" the next time we call it.
1252 ProxyInfo info3;
1253 TestCompletionCallback callback4;
1254 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1255 net::ERR_PROXY_CONNECTION_FAILED,
1256 &info3, callback4.callback(),
1257 NULL, NULL, BoundNetLog());
1258 EXPECT_EQ(ERR_IO_PENDING, rv);
1260 ASSERT_EQ(1u, resolver->pending_requests().size());
1261 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1263 resolver->pending_requests()[0]->results()->UseNamedProxy(
1264 "foopy1:8080;foopy2:9090");
1265 resolver->pending_requests()[0]->CompleteNow(OK);
1267 // The first proxy is not there since the it was added to the bad proxies
1268 // list by the earlier ReconsiderProxyAfterError().
1269 EXPECT_EQ(OK, callback4.WaitForResult());
1270 EXPECT_FALSE(info3.is_direct());
1271 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1273 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1274 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1275 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1278 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
1279 // Test proxy failover when the configuration is bad.
1281 ProxyConfig config(
1282 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1284 config.set_pac_mandatory(true);
1285 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1287 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1289 ProxyService service(config_service, resolver, NULL);
1291 GURL url("http://www.google.com/");
1293 // Get the proxy information.
1294 ProxyInfo info;
1295 TestCompletionCallback callback1;
1296 int rv = service.ResolveProxy(
1297 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1298 BoundNetLog());
1299 EXPECT_EQ(ERR_IO_PENDING, rv);
1301 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1302 resolver->pending_set_pac_script_request()->script_data()->url());
1303 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1304 ASSERT_EQ(1u, resolver->pending_requests().size());
1305 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1307 resolver->pending_requests()[0]->results()->UseNamedProxy(
1308 "foopy1:8080;foopy2:9090");
1309 resolver->pending_requests()[0]->CompleteNow(OK);
1311 // The first item is valid.
1312 EXPECT_EQ(OK, callback1.WaitForResult());
1313 EXPECT_FALSE(info.is_direct());
1314 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1316 // Fake a proxy error.
1317 TestCompletionCallback callback2;
1318 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1319 net::ERR_PROXY_CONNECTION_FAILED,
1320 &info, callback2.callback(), NULL,
1321 NULL, BoundNetLog());
1322 EXPECT_EQ(OK, rv);
1324 // The first proxy is ignored, and the second one is selected.
1325 EXPECT_FALSE(info.is_direct());
1326 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1328 // Fake a PAC failure.
1329 ProxyInfo info2;
1330 TestCompletionCallback callback3;
1331 rv = service.ResolveProxy(
1332 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL,
1333 BoundNetLog());
1334 EXPECT_EQ(ERR_IO_PENDING, rv);
1336 ASSERT_EQ(1u, resolver->pending_requests().size());
1337 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1339 // This simulates a javascript runtime error in the PAC script.
1340 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
1342 // Although the resolver failed, the ProxyService will NOT fall-back
1343 // to a DIRECT connection as it is configured as mandatory.
1344 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1345 callback3.WaitForResult());
1346 EXPECT_FALSE(info2.is_direct());
1347 EXPECT_TRUE(info2.is_empty());
1349 // The PAC script will work properly next time and successfully return a
1350 // proxy list. Since we have not marked the configuration as bad, it should
1351 // "just work" the next time we call it.
1352 ProxyInfo info3;
1353 TestCompletionCallback callback4;
1354 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1355 net::ERR_PROXY_CONNECTION_FAILED,
1356 &info3, callback4.callback(),
1357 NULL, NULL, BoundNetLog());
1358 EXPECT_EQ(ERR_IO_PENDING, rv);
1360 ASSERT_EQ(1u, resolver->pending_requests().size());
1361 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1363 resolver->pending_requests()[0]->results()->UseNamedProxy(
1364 "foopy1:8080;foopy2:9090");
1365 resolver->pending_requests()[0]->CompleteNow(OK);
1367 // The first proxy is not there since the it was added to the bad proxies
1368 // list by the earlier ReconsiderProxyAfterError().
1369 EXPECT_EQ(OK, callback4.WaitForResult());
1370 EXPECT_FALSE(info3.is_direct());
1371 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1374 TEST_F(ProxyServiceTest, ProxyBypassList) {
1375 // Test that the proxy bypass rules are consulted.
1377 TestCompletionCallback callback[2];
1378 ProxyInfo info[2];
1379 ProxyConfig config;
1380 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1381 config.set_auto_detect(false);
1382 config.proxy_rules().bypass_rules.ParseFromString("*.org");
1384 ProxyService service(
1385 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1387 int rv;
1388 GURL url1("http://www.webkit.org");
1389 GURL url2("http://www.webkit.com");
1391 // Request for a .org domain should bypass proxy.
1392 rv = service.ResolveProxy(
1393 url1, net::LOAD_NORMAL, &info[0], callback[0].callback(), NULL, NULL,
1394 BoundNetLog());
1395 EXPECT_EQ(OK, rv);
1396 EXPECT_TRUE(info[0].is_direct());
1398 // Request for a .com domain hits the proxy.
1399 rv = service.ResolveProxy(
1400 url2, net::LOAD_NORMAL, &info[1], callback[1].callback(), NULL, NULL,
1401 BoundNetLog());
1402 EXPECT_EQ(OK, rv);
1403 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
1407 TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
1408 ProxyConfig config;
1409 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1410 config.set_auto_detect(false);
1412 ProxyService service(
1413 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1414 GURL test_url("http://www.msn.com");
1415 ProxyInfo info;
1416 TestCompletionCallback callback;
1417 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1418 callback.callback(), NULL, NULL,
1419 BoundNetLog());
1420 EXPECT_EQ(OK, rv);
1421 EXPECT_FALSE(info.is_direct());
1422 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1425 ProxyService service(
1426 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1427 GURL test_url("ftp://ftp.google.com");
1428 ProxyInfo info;
1429 TestCompletionCallback callback;
1430 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1431 callback.callback(), NULL,
1432 NULL, BoundNetLog());
1433 EXPECT_EQ(OK, rv);
1434 EXPECT_TRUE(info.is_direct());
1435 EXPECT_EQ("direct://", info.proxy_server().ToURI());
1438 ProxyService service(
1439 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1440 GURL test_url("https://webbranch.techcu.com");
1441 ProxyInfo info;
1442 TestCompletionCallback callback;
1443 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1444 callback.callback(), NULL,
1445 NULL, BoundNetLog());
1446 EXPECT_EQ(OK, rv);
1447 EXPECT_FALSE(info.is_direct());
1448 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
1451 config.proxy_rules().ParseFromString("foopy1:8080");
1452 ProxyService service(
1453 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1454 GURL test_url("http://www.microsoft.com");
1455 ProxyInfo info;
1456 TestCompletionCallback callback;
1457 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1458 callback.callback(), NULL,
1459 NULL, BoundNetLog());
1460 EXPECT_EQ(OK, rv);
1461 EXPECT_FALSE(info.is_direct());
1462 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1466 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
1467 // Test that the proxy config source is set correctly when resolving proxies
1468 // using manual proxy rules. Namely, the config source should only be set if
1469 // any of the rules were applied.
1471 ProxyConfig config;
1472 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1473 config.proxy_rules().ParseFromString("https=foopy2:8080");
1474 ProxyService service(
1475 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1476 GURL test_url("http://www.google.com");
1477 ProxyInfo info;
1478 TestCompletionCallback callback;
1479 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1480 callback.callback(), NULL,
1481 NULL, BoundNetLog());
1482 ASSERT_EQ(OK, rv);
1483 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1484 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1487 ProxyConfig config;
1488 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1489 config.proxy_rules().ParseFromString("https=foopy2:8080");
1490 ProxyService service(
1491 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1492 GURL test_url("https://www.google.com");
1493 ProxyInfo info;
1494 TestCompletionCallback callback;
1495 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1496 callback.callback(), NULL,
1497 NULL, BoundNetLog());
1498 ASSERT_EQ(OK, rv);
1499 // Used the HTTPS proxy. So source should be TEST.
1500 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1503 ProxyConfig config;
1504 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1505 ProxyService service(
1506 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1507 GURL test_url("http://www.google.com");
1508 ProxyInfo info;
1509 TestCompletionCallback callback;
1510 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1511 callback.callback(), NULL,
1512 NULL, BoundNetLog());
1513 ASSERT_EQ(OK, rv);
1514 // ProxyConfig is empty. Source should still be TEST.
1515 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1519 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1520 // fall back to the SOCKS proxy.
1521 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
1522 ProxyConfig config;
1523 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1524 config.set_auto_detect(false);
1525 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
1526 config.proxy_rules().type);
1529 ProxyService service(
1530 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1531 GURL test_url("http://www.msn.com");
1532 ProxyInfo info;
1533 TestCompletionCallback callback;
1534 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1535 callback.callback(), NULL,
1536 NULL, BoundNetLog());
1537 EXPECT_EQ(OK, rv);
1538 EXPECT_FALSE(info.is_direct());
1539 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1542 ProxyService service(
1543 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1544 GURL test_url("ftp://ftp.google.com");
1545 ProxyInfo info;
1546 TestCompletionCallback callback;
1547 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1548 callback.callback(), NULL,
1549 NULL, BoundNetLog());
1550 EXPECT_EQ(OK, rv);
1551 EXPECT_FALSE(info.is_direct());
1552 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1555 ProxyService service(
1556 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1557 GURL test_url("https://webbranch.techcu.com");
1558 ProxyInfo info;
1559 TestCompletionCallback callback;
1560 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1561 callback.callback(), NULL,
1562 NULL, BoundNetLog());
1563 EXPECT_EQ(OK, rv);
1564 EXPECT_FALSE(info.is_direct());
1565 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1568 ProxyService service(
1569 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1570 GURL test_url("unknown://www.microsoft.com");
1571 ProxyInfo info;
1572 TestCompletionCallback callback;
1573 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1574 callback.callback(), NULL,
1575 NULL, BoundNetLog());
1576 EXPECT_EQ(OK, rv);
1577 EXPECT_FALSE(info.is_direct());
1578 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1582 // Test cancellation of an in-progress request.
1583 TEST_F(ProxyServiceTest, CancelInProgressRequest) {
1584 MockProxyConfigService* config_service =
1585 new MockProxyConfigService("http://foopy/proxy.pac");
1587 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1589 ProxyService service(config_service, resolver, NULL);
1591 // Start 3 requests.
1593 ProxyInfo info1;
1594 TestCompletionCallback callback1;
1595 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1596 &info1, callback1.callback(), NULL, NULL,
1597 BoundNetLog());
1598 EXPECT_EQ(ERR_IO_PENDING, rv);
1600 // Nothing has been sent to the proxy resolver yet, since the proxy
1601 // resolver has not been configured yet.
1602 ASSERT_EQ(0u, resolver->pending_requests().size());
1604 // Successfully initialize the PAC script.
1605 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1606 resolver->pending_set_pac_script_request()->script_data()->url());
1607 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1609 ASSERT_EQ(1u, resolver->pending_requests().size());
1610 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1612 ProxyInfo info2;
1613 TestCompletionCallback callback2;
1614 ProxyService::PacRequest* request2;
1615 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1616 callback2.callback(), &request2, NULL,
1617 BoundNetLog());
1618 EXPECT_EQ(ERR_IO_PENDING, rv);
1619 ASSERT_EQ(2u, resolver->pending_requests().size());
1620 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1622 ProxyInfo info3;
1623 TestCompletionCallback callback3;
1624 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3,
1625 callback3.callback(), NULL, NULL, BoundNetLog());
1626 EXPECT_EQ(ERR_IO_PENDING, rv);
1627 ASSERT_EQ(3u, resolver->pending_requests().size());
1628 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1630 // Cancel the second request
1631 service.CancelPacRequest(request2);
1633 ASSERT_EQ(2u, resolver->pending_requests().size());
1634 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1635 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url());
1637 // Complete the two un-cancelled requests.
1638 // We complete the last one first, just to mix it up a bit.
1639 resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80");
1640 resolver->pending_requests()[1]->CompleteNow(OK);
1642 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1643 resolver->pending_requests()[0]->CompleteNow(OK);
1645 // Complete and verify that requests ran as expected.
1646 EXPECT_EQ(OK, callback1.WaitForResult());
1647 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1649 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1650 ASSERT_EQ(1u, resolver->cancelled_requests().size());
1651 EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url());
1653 EXPECT_EQ(OK, callback3.WaitForResult());
1654 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1657 // Test the initial PAC download for resolver that expects bytes.
1658 TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
1659 MockProxyConfigService* config_service =
1660 new MockProxyConfigService("http://foopy/proxy.pac");
1662 MockAsyncProxyResolverExpectsBytes* resolver =
1663 new MockAsyncProxyResolverExpectsBytes;
1665 ProxyService service(config_service, resolver, NULL);
1667 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1668 service.SetProxyScriptFetchers(fetcher,
1669 new DoNothingDhcpProxyScriptFetcher());
1671 // Start 3 requests.
1673 ProxyInfo info1;
1674 TestCompletionCallback callback1;
1675 ProxyService::PacRequest* request1;
1676 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1677 &info1, callback1.callback(), &request1, NULL,
1678 BoundNetLog());
1679 EXPECT_EQ(ERR_IO_PENDING, rv);
1681 // The first request should have triggered download of PAC script.
1682 EXPECT_TRUE(fetcher->has_pending_request());
1683 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1685 ProxyInfo info2;
1686 TestCompletionCallback callback2;
1687 ProxyService::PacRequest* request2;
1688 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1689 callback2.callback(), &request2, NULL,
1690 BoundNetLog());
1691 EXPECT_EQ(ERR_IO_PENDING, rv);
1693 ProxyInfo info3;
1694 TestCompletionCallback callback3;
1695 ProxyService::PacRequest* request3;
1696 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3,
1697 callback3.callback(), &request3, NULL,
1698 BoundNetLog());
1699 EXPECT_EQ(ERR_IO_PENDING, rv);
1701 // Nothing has been sent to the resolver yet.
1702 EXPECT_TRUE(resolver->pending_requests().empty());
1704 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1705 service.GetLoadState(request1));
1706 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1707 service.GetLoadState(request2));
1708 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1709 service.GetLoadState(request3));
1711 // At this point the ProxyService should be waiting for the
1712 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1713 // PAC script download completion.
1714 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1716 // Now that the PAC script is downloaded, it will have been sent to the proxy
1717 // resolver.
1718 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1719 resolver->pending_set_pac_script_request()->script_data()->utf16());
1720 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1722 ASSERT_EQ(3u, resolver->pending_requests().size());
1723 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1724 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1725 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1727 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1));
1728 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2));
1729 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3));
1731 // Complete all the requests (in some order).
1732 // Note that as we complete requests, they shift up in |pending_requests()|.
1734 resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80");
1735 resolver->pending_requests()[2]->CompleteNow(OK);
1737 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1738 resolver->pending_requests()[0]->CompleteNow(OK);
1740 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1741 resolver->pending_requests()[0]->CompleteNow(OK);
1743 // Complete and verify that requests ran as expected.
1744 EXPECT_EQ(OK, callback1.WaitForResult());
1745 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1746 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1747 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1748 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
1750 EXPECT_EQ(OK, callback2.WaitForResult());
1751 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1752 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
1753 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
1754 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
1756 EXPECT_EQ(OK, callback3.WaitForResult());
1757 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1758 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
1759 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
1760 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
1763 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1764 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
1765 MockProxyConfigService* config_service =
1766 new MockProxyConfigService("http://foopy/proxy.pac");
1768 MockAsyncProxyResolverExpectsBytes* resolver =
1769 new MockAsyncProxyResolverExpectsBytes;
1771 ProxyService service(config_service, resolver, NULL);
1773 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1774 service.SetProxyScriptFetchers(fetcher,
1775 new DoNothingDhcpProxyScriptFetcher());
1777 // Start 2 requests.
1779 ProxyInfo info1;
1780 TestCompletionCallback callback1;
1781 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1782 &info1, callback1.callback(), NULL, NULL,
1783 BoundNetLog());
1784 EXPECT_EQ(ERR_IO_PENDING, rv);
1786 // The first request should have triggered download of PAC script.
1787 EXPECT_TRUE(fetcher->has_pending_request());
1788 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1790 ProxyInfo info2;
1791 TestCompletionCallback callback2;
1792 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1793 callback2.callback(), NULL, NULL, BoundNetLog());
1794 EXPECT_EQ(ERR_IO_PENDING, rv);
1796 // At this point the ProxyService should be waiting for the
1797 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1798 // PAC script download completion.
1800 // We now change out the ProxyService's script fetcher. We should restart
1801 // the initialization with the new fetcher.
1803 fetcher = new MockProxyScriptFetcher;
1804 service.SetProxyScriptFetchers(fetcher,
1805 new DoNothingDhcpProxyScriptFetcher());
1807 // Nothing has been sent to the resolver yet.
1808 EXPECT_TRUE(resolver->pending_requests().empty());
1810 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1812 // Now that the PAC script is downloaded, it will have been sent to the proxy
1813 // resolver.
1814 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1815 resolver->pending_set_pac_script_request()->script_data()->utf16());
1816 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1818 ASSERT_EQ(2u, resolver->pending_requests().size());
1819 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1820 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1823 // Test cancellation of a request, while the PAC script is being fetched.
1824 TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
1825 MockProxyConfigService* config_service =
1826 new MockProxyConfigService("http://foopy/proxy.pac");
1828 MockAsyncProxyResolverExpectsBytes* resolver =
1829 new MockAsyncProxyResolverExpectsBytes;
1831 ProxyService service(config_service, resolver, NULL);
1833 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1834 service.SetProxyScriptFetchers(fetcher,
1835 new DoNothingDhcpProxyScriptFetcher());
1837 // Start 3 requests.
1838 ProxyInfo info1;
1839 TestCompletionCallback callback1;
1840 ProxyService::PacRequest* request1;
1841 CapturingBoundNetLog log1;
1842 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1843 &info1, callback1.callback(), &request1, NULL,
1844 log1.bound());
1845 EXPECT_EQ(ERR_IO_PENDING, rv);
1847 // The first request should have triggered download of PAC script.
1848 EXPECT_TRUE(fetcher->has_pending_request());
1849 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1851 ProxyInfo info2;
1852 TestCompletionCallback callback2;
1853 ProxyService::PacRequest* request2;
1854 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1855 callback2.callback(), &request2, NULL,
1856 BoundNetLog());
1857 EXPECT_EQ(ERR_IO_PENDING, rv);
1859 ProxyInfo info3;
1860 TestCompletionCallback callback3;
1861 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3,
1862 callback3.callback(), NULL, NULL, BoundNetLog());
1863 EXPECT_EQ(ERR_IO_PENDING, rv);
1865 // Nothing has been sent to the resolver yet.
1866 EXPECT_TRUE(resolver->pending_requests().empty());
1868 // Cancel the first 2 requests.
1869 service.CancelPacRequest(request1);
1870 service.CancelPacRequest(request2);
1872 // At this point the ProxyService should be waiting for the
1873 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1874 // PAC script download completion.
1875 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1877 // Now that the PAC script is downloaded, it will have been sent to the
1878 // proxy resolver.
1879 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1880 resolver->pending_set_pac_script_request()->script_data()->utf16());
1881 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1883 ASSERT_EQ(1u, resolver->pending_requests().size());
1884 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url());
1886 // Complete all the requests.
1887 resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80");
1888 resolver->pending_requests()[0]->CompleteNow(OK);
1890 EXPECT_EQ(OK, callback3.WaitForResult());
1891 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1893 EXPECT_TRUE(resolver->cancelled_requests().empty());
1895 EXPECT_FALSE(callback1.have_result()); // Cancelled.
1896 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1898 CapturingNetLog::CapturedEntryList entries1;
1899 log1.GetEntries(&entries1);
1901 // Check the NetLog for request 1 (which was cancelled) got filled properly.
1902 EXPECT_EQ(4u, entries1.size());
1903 EXPECT_TRUE(LogContainsBeginEvent(
1904 entries1, 0, NetLog::TYPE_PROXY_SERVICE));
1905 EXPECT_TRUE(LogContainsBeginEvent(
1906 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
1907 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1908 // the cancellation occured.
1909 EXPECT_TRUE(LogContainsEvent(
1910 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
1911 EXPECT_TRUE(LogContainsEndEvent(
1912 entries1, 3, NetLog::TYPE_PROXY_SERVICE));
1915 // Test that if auto-detect fails, we fall-back to the custom pac.
1916 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
1917 ProxyConfig config;
1918 config.set_auto_detect(true);
1919 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1920 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1922 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1923 MockAsyncProxyResolverExpectsBytes* resolver =
1924 new MockAsyncProxyResolverExpectsBytes;
1925 ProxyService service(config_service, resolver, NULL);
1927 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1928 service.SetProxyScriptFetchers(fetcher,
1929 new DoNothingDhcpProxyScriptFetcher());
1931 // Start 2 requests.
1933 ProxyInfo info1;
1934 TestCompletionCallback callback1;
1935 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1936 &info1, callback1.callback(), NULL, NULL,
1937 BoundNetLog());
1938 EXPECT_EQ(ERR_IO_PENDING, rv);
1940 ProxyInfo info2;
1941 TestCompletionCallback callback2;
1942 ProxyService::PacRequest* request2;
1943 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1944 callback2.callback(), &request2, NULL,
1945 BoundNetLog());
1946 EXPECT_EQ(ERR_IO_PENDING, rv);
1948 // Check that nothing has been sent to the proxy resolver yet.
1949 ASSERT_EQ(0u, resolver->pending_requests().size());
1951 // It should be trying to auto-detect first -- FAIL the autodetect during
1952 // the script download.
1953 EXPECT_TRUE(fetcher->has_pending_request());
1954 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1955 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
1957 // Next it should be trying the custom PAC url.
1958 EXPECT_TRUE(fetcher->has_pending_request());
1959 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1960 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1962 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1963 resolver->pending_set_pac_script_request()->script_data()->utf16());
1964 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1966 // Now finally, the pending requests should have been sent to the resolver
1967 // (which was initialized with custom PAC script).
1969 ASSERT_EQ(2u, resolver->pending_requests().size());
1970 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1971 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1973 // Complete the pending requests.
1974 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1975 resolver->pending_requests()[1]->CompleteNow(OK);
1976 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1977 resolver->pending_requests()[0]->CompleteNow(OK);
1979 // Verify that requests ran as expected.
1980 EXPECT_EQ(OK, callback1.WaitForResult());
1981 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1982 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1983 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1984 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
1986 EXPECT_EQ(OK, callback2.WaitForResult());
1987 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1988 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
1989 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
1990 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
1993 // This is the same test as FallbackFromAutodetectToCustomPac, except
1994 // the auto-detect script fails parsing rather than downloading.
1995 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
1996 ProxyConfig config;
1997 config.set_auto_detect(true);
1998 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1999 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2001 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2002 MockAsyncProxyResolverExpectsBytes* resolver =
2003 new MockAsyncProxyResolverExpectsBytes;
2004 ProxyService service(config_service, resolver, NULL);
2006 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2007 service.SetProxyScriptFetchers(fetcher,
2008 new DoNothingDhcpProxyScriptFetcher());
2010 // Start 2 requests.
2012 ProxyInfo info1;
2013 TestCompletionCallback callback1;
2014 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2015 &info1, callback1.callback(), NULL, NULL,
2016 BoundNetLog());
2017 EXPECT_EQ(ERR_IO_PENDING, rv);
2019 ProxyInfo info2;
2020 TestCompletionCallback callback2;
2021 ProxyService::PacRequest* request2;
2022 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
2023 callback2.callback(), &request2, NULL,
2024 BoundNetLog());
2025 EXPECT_EQ(ERR_IO_PENDING, rv);
2027 // Check that nothing has been sent to the proxy resolver yet.
2028 ASSERT_EQ(0u, resolver->pending_requests().size());
2030 // It should be trying to auto-detect first -- succeed the download.
2031 EXPECT_TRUE(fetcher->has_pending_request());
2032 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2033 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
2035 // The script contents passed failed basic verification step (since didn't
2036 // contain token FindProxyForURL), so it was never passed to the resolver.
2038 // Next it should be trying the custom PAC url.
2039 EXPECT_TRUE(fetcher->has_pending_request());
2040 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2041 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2043 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2044 resolver->pending_set_pac_script_request()->script_data()->utf16());
2045 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2047 // Now finally, the pending requests should have been sent to the resolver
2048 // (which was initialized with custom PAC script).
2050 ASSERT_EQ(2u, resolver->pending_requests().size());
2051 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2052 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
2054 // Complete the pending requests.
2055 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
2056 resolver->pending_requests()[1]->CompleteNow(OK);
2057 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2058 resolver->pending_requests()[0]->CompleteNow(OK);
2060 // Verify that requests ran as expected.
2061 EXPECT_EQ(OK, callback1.WaitForResult());
2062 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2064 EXPECT_EQ(OK, callback2.WaitForResult());
2065 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2068 // Test that if all of auto-detect, a custom PAC script, and manual settings
2069 // are given, then we will try them in that order.
2070 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
2071 ProxyConfig config;
2072 config.set_auto_detect(true);
2073 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2074 config.proxy_rules().ParseFromString("http=foopy:80");
2076 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2077 MockAsyncProxyResolverExpectsBytes* resolver =
2078 new MockAsyncProxyResolverExpectsBytes;
2079 ProxyService service(config_service, resolver, NULL);
2081 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2082 service.SetProxyScriptFetchers(fetcher,
2083 new DoNothingDhcpProxyScriptFetcher());
2085 // Start 2 requests.
2087 ProxyInfo info1;
2088 TestCompletionCallback callback1;
2089 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2090 &info1, callback1.callback(), NULL, NULL,
2091 BoundNetLog());
2092 EXPECT_EQ(ERR_IO_PENDING, rv);
2094 ProxyInfo info2;
2095 TestCompletionCallback callback2;
2096 ProxyService::PacRequest* request2;
2097 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
2098 callback2.callback(), &request2, NULL,
2099 BoundNetLog());
2100 EXPECT_EQ(ERR_IO_PENDING, rv);
2102 // Check that nothing has been sent to the proxy resolver yet.
2103 ASSERT_EQ(0u, resolver->pending_requests().size());
2105 // It should be trying to auto-detect first -- fail the download.
2106 EXPECT_TRUE(fetcher->has_pending_request());
2107 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2108 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2110 // Next it should be trying the custom PAC url -- fail the download.
2111 EXPECT_TRUE(fetcher->has_pending_request());
2112 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2113 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2115 // Since we never managed to initialize a ProxyResolver, nothing should have
2116 // been sent to it.
2117 ASSERT_EQ(0u, resolver->pending_requests().size());
2119 // Verify that requests ran as expected -- they should have fallen back to
2120 // the manual proxy configuration for HTTP urls.
2121 EXPECT_EQ(OK, callback1.WaitForResult());
2122 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
2124 EXPECT_EQ(OK, callback2.WaitForResult());
2125 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
2128 // Test that the bypass rules are NOT applied when using autodetect.
2129 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
2130 ProxyConfig config;
2131 config.set_auto_detect(true);
2132 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2133 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
2134 config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
2136 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2137 MockAsyncProxyResolverExpectsBytes* resolver =
2138 new MockAsyncProxyResolverExpectsBytes;
2139 ProxyService service(config_service, resolver, NULL);
2141 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2142 service.SetProxyScriptFetchers(fetcher,
2143 new DoNothingDhcpProxyScriptFetcher());
2145 // Start 1 requests.
2147 ProxyInfo info1;
2148 TestCompletionCallback callback1;
2149 int rv = service.ResolveProxy(
2150 GURL("http://www.google.com"), net::LOAD_NORMAL, &info1,
2151 callback1.callback(), NULL, NULL, BoundNetLog());
2152 EXPECT_EQ(ERR_IO_PENDING, rv);
2154 // Check that nothing has been sent to the proxy resolver yet.
2155 ASSERT_EQ(0u, resolver->pending_requests().size());
2157 // It should be trying to auto-detect first -- succeed the download.
2158 EXPECT_TRUE(fetcher->has_pending_request());
2159 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2160 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2162 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2163 resolver->pending_set_pac_script_request()->script_data()->utf16());
2164 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2166 ASSERT_EQ(1u, resolver->pending_requests().size());
2167 EXPECT_EQ(GURL("http://www.google.com"),
2168 resolver->pending_requests()[0]->url());
2170 // Complete the pending request.
2171 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2172 resolver->pending_requests()[0]->CompleteNow(OK);
2174 // Verify that request ran as expected.
2175 EXPECT_EQ(OK, callback1.WaitForResult());
2176 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2178 // Start another request, it should pickup the bypass item.
2179 ProxyInfo info2;
2180 TestCompletionCallback callback2;
2181 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2182 &info2, callback2.callback(), NULL, NULL,
2183 BoundNetLog());
2184 EXPECT_EQ(ERR_IO_PENDING, rv);
2186 ASSERT_EQ(1u, resolver->pending_requests().size());
2187 EXPECT_EQ(GURL("http://www.google.com"),
2188 resolver->pending_requests()[0]->url());
2190 // Complete the pending request.
2191 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2192 resolver->pending_requests()[0]->CompleteNow(OK);
2194 EXPECT_EQ(OK, callback2.WaitForResult());
2195 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2198 // Delete the ProxyService while InitProxyResolver has an outstanding
2199 // request to the script fetcher. When run under valgrind, should not
2200 // have any memory errors (used to be that the ProxyScriptFetcher was
2201 // being deleted prior to the InitProxyResolver).
2202 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
2203 ProxyConfig config =
2204 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
2206 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2207 MockAsyncProxyResolverExpectsBytes* resolver =
2208 new MockAsyncProxyResolverExpectsBytes;
2209 ProxyService service(config_service, resolver, NULL);
2211 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2212 service.SetProxyScriptFetchers(fetcher,
2213 new DoNothingDhcpProxyScriptFetcher());
2215 // Start 1 request.
2217 ProxyInfo info1;
2218 TestCompletionCallback callback1;
2219 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2220 &info1, callback1.callback(), NULL, NULL,
2221 BoundNetLog());
2222 EXPECT_EQ(ERR_IO_PENDING, rv);
2224 // Check that nothing has been sent to the proxy resolver yet.
2225 ASSERT_EQ(0u, resolver->pending_requests().size());
2227 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
2228 // and be waiting on that to complete.
2229 EXPECT_TRUE(fetcher->has_pending_request());
2230 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2233 // Delete the ProxyService while InitProxyResolver has an outstanding
2234 // request to the proxy resolver. When run under valgrind, should not
2235 // have any memory errors (used to be that the ProxyResolver was
2236 // being deleted prior to the InitProxyResolver).
2237 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
2238 MockProxyConfigService* config_service =
2239 new MockProxyConfigService("http://foopy/proxy.pac");
2241 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
2243 ProxyService service(config_service, resolver, NULL);
2245 GURL url("http://www.google.com/");
2247 ProxyInfo info;
2248 TestCompletionCallback callback;
2249 int rv = service.ResolveProxy(
2250 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
2251 BoundNetLog());
2252 EXPECT_EQ(ERR_IO_PENDING, rv);
2254 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2255 resolver->pending_set_pac_script_request()->script_data()->url());
2258 TEST_F(ProxyServiceTest, ResetProxyConfigService) {
2259 ProxyConfig config1;
2260 config1.proxy_rules().ParseFromString("foopy1:8080");
2261 config1.set_auto_detect(false);
2262 ProxyService service(
2263 new MockProxyConfigService(config1),
2264 new MockAsyncProxyResolverExpectsBytes, NULL);
2266 ProxyInfo info;
2267 TestCompletionCallback callback1;
2268 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2269 &info, callback1.callback(), NULL, NULL,
2270 BoundNetLog());
2271 EXPECT_EQ(OK, rv);
2272 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
2274 ProxyConfig config2;
2275 config2.proxy_rules().ParseFromString("foopy2:8080");
2276 config2.set_auto_detect(false);
2277 service.ResetConfigService(new MockProxyConfigService(config2));
2278 TestCompletionCallback callback2;
2279 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info,
2280 callback2.callback(), NULL, NULL, BoundNetLog());
2281 EXPECT_EQ(OK, rv);
2282 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
2285 // Test that when going from a configuration that required PAC to one
2286 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2287 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
2288 ProxyConfig config = ProxyConfig::CreateAutoDetect();
2290 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2291 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
2292 ProxyService service(config_service, resolver, NULL);
2294 // Start 1 request.
2296 ProxyInfo info1;
2297 TestCompletionCallback callback1;
2298 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2299 &info1, callback1.callback(), NULL, NULL,
2300 BoundNetLog());
2301 EXPECT_EQ(ERR_IO_PENDING, rv);
2303 // Check that nothing has been sent to the proxy resolver yet.
2304 ASSERT_EQ(0u, resolver->pending_requests().size());
2306 // Successfully set the autodetect script.
2307 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT,
2308 resolver->pending_set_pac_script_request()->script_data()->type());
2309 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2311 // Complete the pending request.
2312 ASSERT_EQ(1u, resolver->pending_requests().size());
2313 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2314 resolver->pending_requests()[0]->CompleteNow(OK);
2316 // Verify that request ran as expected.
2317 EXPECT_EQ(OK, callback1.WaitForResult());
2318 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2320 // Force the ProxyService to pull down a new proxy configuration.
2321 // (Even though the configuration isn't old/bad).
2323 // This new configuration no longer has auto_detect set, so
2324 // requests should complete synchronously now as direct-connect.
2325 config_service->SetConfig(ProxyConfig::CreateDirect());
2327 // Start another request -- the effective configuration has changed.
2328 ProxyInfo info2;
2329 TestCompletionCallback callback2;
2330 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2331 &info2, callback2.callback(), NULL, NULL,
2332 BoundNetLog());
2333 EXPECT_EQ(OK, rv);
2335 EXPECT_TRUE(info2.is_direct());
2338 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
2339 MockProxyConfigService* config_service =
2340 new MockProxyConfigService("http://foopy/proxy.pac");
2342 MockAsyncProxyResolverExpectsBytes* resolver =
2343 new MockAsyncProxyResolverExpectsBytes;
2345 CapturingNetLog log;
2347 ProxyService service(config_service, resolver, &log);
2349 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2350 service.SetProxyScriptFetchers(fetcher,
2351 new DoNothingDhcpProxyScriptFetcher());
2353 // Disable the "wait after IP address changes" hack, so this unit-test can
2354 // complete quickly.
2355 service.set_stall_proxy_auto_config_delay(base::TimeDelta());
2357 // Start 1 request.
2359 ProxyInfo info1;
2360 TestCompletionCallback callback1;
2361 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2362 &info1, callback1.callback(), NULL, NULL,
2363 BoundNetLog());
2364 EXPECT_EQ(ERR_IO_PENDING, rv);
2366 // The first request should have triggered initial download of PAC script.
2367 EXPECT_TRUE(fetcher->has_pending_request());
2368 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2370 // Nothing has been sent to the resolver yet.
2371 EXPECT_TRUE(resolver->pending_requests().empty());
2373 // At this point the ProxyService should be waiting for the
2374 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2375 // PAC script download completion.
2376 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2378 // Now that the PAC script is downloaded, the request will have been sent to
2379 // the proxy resolver.
2380 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2381 resolver->pending_set_pac_script_request()->script_data()->utf16());
2382 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2384 ASSERT_EQ(1u, resolver->pending_requests().size());
2385 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2387 // Complete the pending request.
2388 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2389 resolver->pending_requests()[0]->CompleteNow(OK);
2391 // Wait for completion callback, and verify that the request ran as expected.
2392 EXPECT_EQ(OK, callback1.WaitForResult());
2393 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2395 // Now simluate a change in the network. The ProxyConfigService is still
2396 // going to return the same PAC URL as before, but this URL needs to be
2397 // refetched on the new network.
2398 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2399 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2401 // Start a second request.
2402 ProxyInfo info2;
2403 TestCompletionCallback callback2;
2404 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
2405 callback2.callback(), NULL, NULL, BoundNetLog());
2406 EXPECT_EQ(ERR_IO_PENDING, rv);
2408 // This second request should have triggered the re-download of the PAC
2409 // script (since we marked the network as having changed).
2410 EXPECT_TRUE(fetcher->has_pending_request());
2411 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2413 // Nothing has been sent to the resolver yet.
2414 EXPECT_TRUE(resolver->pending_requests().empty());
2416 // Simulate the PAC script fetch as having completed (this time with
2417 // different data).
2418 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2420 // Now that the PAC script is downloaded, the second request will have been
2421 // sent to the proxy resolver.
2422 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2423 resolver->pending_set_pac_script_request()->script_data()->utf16());
2424 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2426 ASSERT_EQ(1u, resolver->pending_requests().size());
2427 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2429 // Complete the pending second request.
2430 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2431 resolver->pending_requests()[0]->CompleteNow(OK);
2433 // Wait for completion callback, and verify that the request ran as expected.
2434 EXPECT_EQ(OK, callback2.WaitForResult());
2435 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2437 // Check that the expected events were output to the log stream. In particular
2438 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2439 // setup), and NOT a second time when the IP address changed.
2440 CapturingNetLog::CapturedEntryList entries;
2441 log.GetEntries(&entries);
2443 EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
2444 NetLog::TYPE_PROXY_CONFIG_CHANGED));
2445 ASSERT_EQ(9u, entries.size());
2446 for (size_t i = 1; i < entries.size(); ++i)
2447 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
2450 // This test verifies that the PAC script specified by the settings is
2451 // periodically polled for changes. Specifically, if the initial fetch fails due
2452 // to a network error, we will eventually re-configure the service to use the
2453 // script once it becomes available.
2454 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
2455 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2456 // runs quickly.
2457 ImmediatePollPolicy poll_policy;
2458 ProxyService::set_pac_script_poll_policy(&poll_policy);
2460 MockProxyConfigService* config_service =
2461 new MockProxyConfigService("http://foopy/proxy.pac");
2463 MockAsyncProxyResolverExpectsBytes* resolver =
2464 new MockAsyncProxyResolverExpectsBytes;
2466 ProxyService service(config_service, resolver, NULL);
2468 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2469 service.SetProxyScriptFetchers(fetcher,
2470 new DoNothingDhcpProxyScriptFetcher());
2472 // Start 1 request.
2474 ProxyInfo info1;
2475 TestCompletionCallback callback1;
2476 int rv = service.ResolveProxy(
2477 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2478 NULL, NULL, BoundNetLog());
2479 EXPECT_EQ(ERR_IO_PENDING, rv);
2481 // The first request should have triggered initial download of PAC script.
2482 EXPECT_TRUE(fetcher->has_pending_request());
2483 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2485 // Nothing has been sent to the resolver yet.
2486 EXPECT_TRUE(resolver->pending_requests().empty());
2488 // At this point the ProxyService should be waiting for the
2489 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2490 // PAC script download completion.
2492 // We simulate a failed download attempt, the proxy service should now
2493 // fall-back to DIRECT connections.
2494 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2496 ASSERT_TRUE(resolver->pending_requests().empty());
2498 // Wait for completion callback, and verify it used DIRECT.
2499 EXPECT_EQ(OK, callback1.WaitForResult());
2500 EXPECT_TRUE(info1.is_direct());
2502 // At this point we have initialized the proxy service using a PAC script,
2503 // however it failed and fell-back to DIRECT.
2505 // A background task to periodically re-check the PAC script for validity will
2506 // have been started. We will now wait for the next download attempt to start.
2508 // Note that we shouldn't have to wait long here, since our test enables a
2509 // special unit-test mode.
2510 fetcher->WaitUntilFetch();
2512 ASSERT_TRUE(resolver->pending_requests().empty());
2514 // Make sure that our background checker is trying to download the expected
2515 // PAC script (same one as before). This time we will simulate a successful
2516 // download of the script.
2517 EXPECT_TRUE(fetcher->has_pending_request());
2518 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2519 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2521 base::MessageLoop::current()->RunUntilIdle();
2523 // Now that the PAC script is downloaded, it should be used to initialize the
2524 // ProxyResolver. Simulate a successful parse.
2525 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2526 resolver->pending_set_pac_script_request()->script_data()->utf16());
2527 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2529 // At this point the ProxyService should have re-configured itself to use the
2530 // PAC script (thereby recovering from the initial fetch failure). We will
2531 // verify that the next Resolve request uses the resolver rather than
2532 // DIRECT.
2534 // Start a second request.
2535 ProxyInfo info2;
2536 TestCompletionCallback callback2;
2537 rv = service.ResolveProxy(
2538 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2539 NULL, NULL, BoundNetLog());
2540 EXPECT_EQ(ERR_IO_PENDING, rv);
2542 // Check that it was sent to the resolver.
2543 ASSERT_EQ(1u, resolver->pending_requests().size());
2544 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2546 // Complete the pending second request.
2547 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2548 resolver->pending_requests()[0]->CompleteNow(OK);
2550 // Wait for completion callback, and verify that the request ran as expected.
2551 EXPECT_EQ(OK, callback2.WaitForResult());
2552 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2555 // This test verifies that the PAC script specified by the settings is
2556 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2557 // however at a later time its *contents* change, we will eventually
2558 // re-configure the service to use the new script.
2559 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
2560 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2561 // runs quickly.
2562 ImmediatePollPolicy poll_policy;
2563 ProxyService::set_pac_script_poll_policy(&poll_policy);
2565 MockProxyConfigService* config_service =
2566 new MockProxyConfigService("http://foopy/proxy.pac");
2568 MockAsyncProxyResolverExpectsBytes* resolver =
2569 new MockAsyncProxyResolverExpectsBytes;
2571 ProxyService service(config_service, resolver, NULL);
2573 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2574 service.SetProxyScriptFetchers(fetcher,
2575 new DoNothingDhcpProxyScriptFetcher());
2577 // Start 1 request.
2579 ProxyInfo info1;
2580 TestCompletionCallback callback1;
2581 int rv = service.ResolveProxy(
2582 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2583 NULL, NULL, BoundNetLog());
2584 EXPECT_EQ(ERR_IO_PENDING, rv);
2586 // The first request should have triggered initial download of PAC script.
2587 EXPECT_TRUE(fetcher->has_pending_request());
2588 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2590 // Nothing has been sent to the resolver yet.
2591 EXPECT_TRUE(resolver->pending_requests().empty());
2593 // At this point the ProxyService should be waiting for the
2594 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2595 // PAC script download completion.
2596 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2598 // Now that the PAC script is downloaded, the request will have been sent to
2599 // the proxy resolver.
2600 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2601 resolver->pending_set_pac_script_request()->script_data()->utf16());
2602 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2604 ASSERT_EQ(1u, resolver->pending_requests().size());
2605 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2607 // Complete the pending request.
2608 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2609 resolver->pending_requests()[0]->CompleteNow(OK);
2611 // Wait for completion callback, and verify that the request ran as expected.
2612 EXPECT_EQ(OK, callback1.WaitForResult());
2613 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2615 // At this point we have initialized the proxy service using a PAC script.
2617 // A background task to periodically re-check the PAC script for validity will
2618 // have been started. We will now wait for the next download attempt to start.
2620 // Note that we shouldn't have to wait long here, since our test enables a
2621 // special unit-test mode.
2622 fetcher->WaitUntilFetch();
2624 ASSERT_TRUE(resolver->pending_requests().empty());
2626 // Make sure that our background checker is trying to download the expected
2627 // PAC script (same one as before). This time we will simulate a successful
2628 // download of a DIFFERENT script.
2629 EXPECT_TRUE(fetcher->has_pending_request());
2630 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2631 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2633 base::MessageLoop::current()->RunUntilIdle();
2635 // Now that the PAC script is downloaded, it should be used to initialize the
2636 // ProxyResolver. Simulate a successful parse.
2637 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2638 resolver->pending_set_pac_script_request()->script_data()->utf16());
2639 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2641 // At this point the ProxyService should have re-configured itself to use the
2642 // new PAC script.
2644 // Start a second request.
2645 ProxyInfo info2;
2646 TestCompletionCallback callback2;
2647 rv = service.ResolveProxy(
2648 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2649 NULL, NULL, BoundNetLog());
2650 EXPECT_EQ(ERR_IO_PENDING, rv);
2652 // Check that it was sent to the resolver.
2653 ASSERT_EQ(1u, resolver->pending_requests().size());
2654 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2656 // Complete the pending second request.
2657 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2658 resolver->pending_requests()[0]->CompleteNow(OK);
2660 // Wait for completion callback, and verify that the request ran as expected.
2661 EXPECT_EQ(OK, callback2.WaitForResult());
2662 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2665 // This test verifies that the PAC script specified by the settings is
2666 // periodically polled for changes. Specifically, if the initial fetch succeeds
2667 // and so does the next poll, however the contents of the downloaded script
2668 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2669 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
2670 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2671 // runs quickly.
2672 ImmediatePollPolicy poll_policy;
2673 ProxyService::set_pac_script_poll_policy(&poll_policy);
2675 MockProxyConfigService* config_service =
2676 new MockProxyConfigService("http://foopy/proxy.pac");
2678 MockAsyncProxyResolverExpectsBytes* resolver =
2679 new MockAsyncProxyResolverExpectsBytes;
2681 ProxyService service(config_service, resolver, NULL);
2683 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2684 service.SetProxyScriptFetchers(fetcher,
2685 new DoNothingDhcpProxyScriptFetcher());
2687 // Start 1 request.
2689 ProxyInfo info1;
2690 TestCompletionCallback callback1;
2691 int rv = service.ResolveProxy(
2692 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2693 NULL, NULL, BoundNetLog());
2694 EXPECT_EQ(ERR_IO_PENDING, rv);
2696 // The first request should have triggered initial download of PAC script.
2697 EXPECT_TRUE(fetcher->has_pending_request());
2698 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2700 // Nothing has been sent to the resolver yet.
2701 EXPECT_TRUE(resolver->pending_requests().empty());
2703 // At this point the ProxyService should be waiting for the
2704 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2705 // PAC script download completion.
2706 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2708 // Now that the PAC script is downloaded, the request will have been sent to
2709 // the proxy resolver.
2710 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2711 resolver->pending_set_pac_script_request()->script_data()->utf16());
2712 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2714 ASSERT_EQ(1u, resolver->pending_requests().size());
2715 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2717 // Complete the pending request.
2718 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2719 resolver->pending_requests()[0]->CompleteNow(OK);
2721 // Wait for completion callback, and verify that the request ran as expected.
2722 EXPECT_EQ(OK, callback1.WaitForResult());
2723 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2725 // At this point we have initialized the proxy service using a PAC script.
2727 // A background task to periodically re-check the PAC script for validity will
2728 // have been started. We will now wait for the next download attempt to start.
2730 // Note that we shouldn't have to wait long here, since our test enables a
2731 // special unit-test mode.
2732 fetcher->WaitUntilFetch();
2734 ASSERT_TRUE(resolver->pending_requests().empty());
2736 // Make sure that our background checker is trying to download the expected
2737 // PAC script (same one as before). We will simulate the same response as
2738 // last time (i.e. the script is unchanged).
2739 EXPECT_TRUE(fetcher->has_pending_request());
2740 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2741 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2743 base::MessageLoop::current()->RunUntilIdle();
2745 ASSERT_FALSE(resolver->has_pending_set_pac_script_request());
2747 // At this point the ProxyService is still running the same PAC script as
2748 // before.
2750 // Start a second request.
2751 ProxyInfo info2;
2752 TestCompletionCallback callback2;
2753 rv = service.ResolveProxy(
2754 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2755 NULL, NULL, BoundNetLog());
2756 EXPECT_EQ(ERR_IO_PENDING, rv);
2758 // Check that it was sent to the resolver.
2759 ASSERT_EQ(1u, resolver->pending_requests().size());
2760 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2762 // Complete the pending second request.
2763 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2764 resolver->pending_requests()[0]->CompleteNow(OK);
2766 // Wait for completion callback, and verify that the request ran as expected.
2767 EXPECT_EQ(OK, callback2.WaitForResult());
2768 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2771 // This test verifies that the PAC script specified by the settings is
2772 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2773 // however at a later time it starts to fail, we should re-configure the
2774 // ProxyService to stop using that PAC script.
2775 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
2776 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2777 // runs quickly.
2778 ImmediatePollPolicy poll_policy;
2779 ProxyService::set_pac_script_poll_policy(&poll_policy);
2781 MockProxyConfigService* config_service =
2782 new MockProxyConfigService("http://foopy/proxy.pac");
2784 MockAsyncProxyResolverExpectsBytes* resolver =
2785 new MockAsyncProxyResolverExpectsBytes;
2787 ProxyService service(config_service, resolver, NULL);
2789 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2790 service.SetProxyScriptFetchers(fetcher,
2791 new DoNothingDhcpProxyScriptFetcher());
2793 // Start 1 request.
2795 ProxyInfo info1;
2796 TestCompletionCallback callback1;
2797 int rv = service.ResolveProxy(
2798 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2799 NULL, NULL, BoundNetLog());
2800 EXPECT_EQ(ERR_IO_PENDING, rv);
2802 // The first request should have triggered initial download of PAC script.
2803 EXPECT_TRUE(fetcher->has_pending_request());
2804 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2806 // Nothing has been sent to the resolver yet.
2807 EXPECT_TRUE(resolver->pending_requests().empty());
2809 // At this point the ProxyService should be waiting for the
2810 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2811 // PAC script download completion.
2812 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2814 // Now that the PAC script is downloaded, the request will have been sent to
2815 // the proxy resolver.
2816 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2817 resolver->pending_set_pac_script_request()->script_data()->utf16());
2818 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2820 ASSERT_EQ(1u, resolver->pending_requests().size());
2821 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2823 // Complete the pending request.
2824 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2825 resolver->pending_requests()[0]->CompleteNow(OK);
2827 // Wait for completion callback, and verify that the request ran as expected.
2828 EXPECT_EQ(OK, callback1.WaitForResult());
2829 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2831 // At this point we have initialized the proxy service using a PAC script.
2833 // A background task to periodically re-check the PAC script for validity will
2834 // have been started. We will now wait for the next download attempt to start.
2836 // Note that we shouldn't have to wait long here, since our test enables a
2837 // special unit-test mode.
2838 fetcher->WaitUntilFetch();
2840 ASSERT_TRUE(resolver->pending_requests().empty());
2842 // Make sure that our background checker is trying to download the expected
2843 // PAC script (same one as before). This time we will simulate a failure
2844 // to download the script.
2845 EXPECT_TRUE(fetcher->has_pending_request());
2846 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2847 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2849 base::MessageLoop::current()->RunUntilIdle();
2851 // At this point the ProxyService should have re-configured itself to use
2852 // DIRECT connections rather than the given proxy resolver.
2854 // Start a second request.
2855 ProxyInfo info2;
2856 TestCompletionCallback callback2;
2857 rv = service.ResolveProxy(
2858 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2859 NULL, NULL, BoundNetLog());
2860 EXPECT_EQ(OK, rv);
2861 EXPECT_TRUE(info2.is_direct());
2864 // Tests that the code which decides at what times to poll the PAC
2865 // script follows the expected policy.
2866 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) {
2867 // Retrieve the internal polling policy implementation used by ProxyService.
2868 scoped_ptr<ProxyService::PacPollPolicy> policy =
2869 ProxyService::CreateDefaultPacPollPolicy();
2871 int error;
2872 ProxyService::PacPollPolicy::Mode mode;
2873 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1);
2874 base::TimeDelta delay = initial_delay;
2876 // --------------------------------------------------
2877 // Test the poll sequence in response to a failure.
2878 // --------------------------------------------------
2879 error = ERR_NAME_NOT_RESOLVED;
2881 // Poll #0
2882 mode = policy->GetNextDelay(error, initial_delay, &delay);
2883 EXPECT_EQ(8, delay.InSeconds());
2884 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
2886 // Poll #1
2887 mode = policy->GetNextDelay(error, delay, &delay);
2888 EXPECT_EQ(32, delay.InSeconds());
2889 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2891 // Poll #2
2892 mode = policy->GetNextDelay(error, delay, &delay);
2893 EXPECT_EQ(120, delay.InSeconds());
2894 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2896 // Poll #3
2897 mode = policy->GetNextDelay(error, delay, &delay);
2898 EXPECT_EQ(14400, delay.InSeconds());
2899 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2901 // Poll #4
2902 mode = policy->GetNextDelay(error, delay, &delay);
2903 EXPECT_EQ(14400, delay.InSeconds());
2904 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2906 // --------------------------------------------------
2907 // Test the poll sequence in response to a success.
2908 // --------------------------------------------------
2909 error = OK;
2911 // Poll #0
2912 mode = policy->GetNextDelay(error, initial_delay, &delay);
2913 EXPECT_EQ(43200, delay.InSeconds());
2914 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2916 // Poll #1
2917 mode = policy->GetNextDelay(error, delay, &delay);
2918 EXPECT_EQ(43200, delay.InSeconds());
2919 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2921 // Poll #2
2922 mode = policy->GetNextDelay(error, delay, &delay);
2923 EXPECT_EQ(43200, delay.InSeconds());
2924 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2927 // This tests the polling of the PAC script. Specifically, it tests that
2928 // polling occurs in response to user activity.
2929 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
2930 ImmediateAfterActivityPollPolicy poll_policy;
2931 ProxyService::set_pac_script_poll_policy(&poll_policy);
2933 MockProxyConfigService* config_service =
2934 new MockProxyConfigService("http://foopy/proxy.pac");
2936 MockAsyncProxyResolverExpectsBytes* resolver =
2937 new MockAsyncProxyResolverExpectsBytes;
2939 ProxyService service(config_service, resolver, NULL);
2941 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2942 service.SetProxyScriptFetchers(fetcher,
2943 new DoNothingDhcpProxyScriptFetcher());
2945 // Start 1 request.
2947 ProxyInfo info1;
2948 TestCompletionCallback callback1;
2949 int rv = service.ResolveProxy(
2950 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2951 NULL, NULL, BoundNetLog());
2952 EXPECT_EQ(ERR_IO_PENDING, rv);
2954 // The first request should have triggered initial download of PAC script.
2955 EXPECT_TRUE(fetcher->has_pending_request());
2956 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2958 // Nothing has been sent to the resolver yet.
2959 EXPECT_TRUE(resolver->pending_requests().empty());
2961 // At this point the ProxyService should be waiting for the
2962 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2963 // PAC script download completion.
2964 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2966 // Now that the PAC script is downloaded, the request will have been sent to
2967 // the proxy resolver.
2968 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2969 resolver->pending_set_pac_script_request()->script_data()->utf16());
2970 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2972 ASSERT_EQ(1u, resolver->pending_requests().size());
2973 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2975 // Complete the pending request.
2976 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2977 resolver->pending_requests()[0]->CompleteNow(OK);
2979 // Wait for completion callback, and verify that the request ran as expected.
2980 EXPECT_EQ(OK, callback1.WaitForResult());
2981 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2983 // At this point we have initialized the proxy service using a PAC script.
2984 // Our PAC poller is set to update ONLY in response to network activity,
2985 // (i.e. another call to ResolveProxy()).
2987 ASSERT_FALSE(fetcher->has_pending_request());
2988 ASSERT_TRUE(resolver->pending_requests().empty());
2990 // Start a second request.
2991 ProxyInfo info2;
2992 TestCompletionCallback callback2;
2993 rv = service.ResolveProxy(
2994 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2995 NULL, NULL, BoundNetLog());
2996 EXPECT_EQ(ERR_IO_PENDING, rv);
2998 // This request should have sent work to the resolver; complete it.
2999 ASSERT_EQ(1u, resolver->pending_requests().size());
3000 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
3001 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
3002 resolver->pending_requests()[0]->CompleteNow(OK);
3004 EXPECT_EQ(OK, callback2.WaitForResult());
3005 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
3007 // In response to getting that resolve request, the poller should have
3008 // started the next poll, and made it as far as to request the download.
3010 EXPECT_TRUE(fetcher->has_pending_request());
3011 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3013 // This time we will fail the download, to simulate a PAC script change.
3014 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
3016 // Drain the message loop, so ProxyService is notified of the change
3017 // and has a chance to re-configure itself.
3018 base::MessageLoop::current()->RunUntilIdle();
3020 // Start a third request -- this time we expect to get a direct connection
3021 // since the PAC script poller experienced a failure.
3022 ProxyInfo info3;
3023 TestCompletionCallback callback3;
3024 rv = service.ResolveProxy(
3025 GURL("http://request3"), net::LOAD_NORMAL, &info3, callback3.callback(),
3026 NULL, NULL, BoundNetLog());
3027 EXPECT_EQ(OK, rv);
3028 EXPECT_TRUE(info3.is_direct());
3031 } // namespace net