Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / net / proxy / proxy_service_unittest.cc
blob4f1569057912190d253309f40afd65266d254f3c
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/network_delegate_impl.h"
16 #include "net/base/test_completion_callback.h"
17 #include "net/log/net_log.h"
18 #include "net/log/net_log_unittest.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 Mode GetNextDelay(int error,
41 base::TimeDelta current_delay,
42 base::TimeDelta* next_delay) const override {
43 *next_delay = base::TimeDelta::FromMilliseconds(1);
44 return MODE_USE_TIMER;
47 private:
48 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy);
51 // This polling policy chooses a fantastically large delay. In other words, it
52 // will never trigger a poll
53 class NeverPollPolicy : public ProxyService::PacPollPolicy {
54 public:
55 NeverPollPolicy() {}
57 Mode GetNextDelay(int error,
58 base::TimeDelta current_delay,
59 base::TimeDelta* next_delay) const override {
60 *next_delay = base::TimeDelta::FromDays(60);
61 return MODE_USE_TIMER;
64 private:
65 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy);
68 // This polling policy starts a poll immediately after network activity.
69 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
70 public:
71 ImmediateAfterActivityPollPolicy() {}
73 Mode GetNextDelay(int error,
74 base::TimeDelta current_delay,
75 base::TimeDelta* next_delay) const override {
76 *next_delay = base::TimeDelta();
77 return MODE_START_AFTER_ACTIVITY;
80 private:
81 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy);
84 // This test fixture is used to partially disable the background polling done by
85 // the ProxyService (which it uses to detect whenever its PAC script contents or
86 // WPAD results have changed).
88 // We disable the feature by setting the poll interval to something really
89 // large, so it will never actually be reached even on the slowest bots that run
90 // these tests.
92 // We disable the polling in order to avoid any timing dependencies in the
93 // tests. If the bot were to run the tests very slowly and we hadn't disabled
94 // polling, then it might start a background re-try in the middle of our test
95 // and confuse our expectations leading to flaky failures.
97 // The tests which verify the polling code re-enable the polling behavior but
98 // are careful to avoid timing problems.
99 class ProxyServiceTest : public testing::Test {
100 protected:
101 void SetUp() override {
102 testing::Test::SetUp();
103 previous_policy_ =
104 ProxyService::set_pac_script_poll_policy(&never_poll_policy_);
107 void TearDown() override {
108 // Restore the original policy.
109 ProxyService::set_pac_script_poll_policy(previous_policy_);
110 testing::Test::TearDown();
113 private:
114 NeverPollPolicy never_poll_policy_;
115 const ProxyService::PacPollPolicy* previous_policy_;
118 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
119 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
121 class MockProxyConfigService: public ProxyConfigService {
122 public:
123 explicit MockProxyConfigService(const ProxyConfig& config)
124 : availability_(CONFIG_VALID),
125 config_(config) {
128 explicit MockProxyConfigService(const std::string& pac_url)
129 : availability_(CONFIG_VALID),
130 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) {
133 void AddObserver(Observer* observer) override {
134 observers_.AddObserver(observer);
137 void RemoveObserver(Observer* observer) override {
138 observers_.RemoveObserver(observer);
141 ConfigAvailability GetLatestProxyConfig(ProxyConfig* results) override {
142 if (availability_ == CONFIG_VALID)
143 *results = config_;
144 return availability_;
147 void SetConfig(const ProxyConfig& config) {
148 availability_ = CONFIG_VALID;
149 config_ = config;
150 FOR_EACH_OBSERVER(Observer, observers_,
151 OnProxyConfigChanged(config_, availability_));
154 private:
155 ConfigAvailability availability_;
156 ProxyConfig config_;
157 ObserverList<Observer, true> observers_;
160 // A test network delegate that exercises the OnResolveProxy callback.
161 class TestResolveProxyNetworkDelegate : public NetworkDelegateImpl {
162 public:
163 TestResolveProxyNetworkDelegate()
164 : on_resolve_proxy_called_(false),
165 add_proxy_(false),
166 remove_proxy_(false),
167 proxy_service_(NULL) {
170 void OnResolveProxy(const GURL& url,
171 int load_flags,
172 const ProxyService& proxy_service,
173 ProxyInfo* result) override {
174 on_resolve_proxy_called_ = true;
175 proxy_service_ = &proxy_service;
176 DCHECK(!add_proxy_ || !remove_proxy_);
177 if (add_proxy_) {
178 result->UseNamedProxy("delegate_proxy.com");
179 } else if (remove_proxy_) {
180 result->UseDirect();
184 bool on_resolve_proxy_called() const {
185 return on_resolve_proxy_called_;
188 void set_add_proxy(bool add_proxy) {
189 add_proxy_ = add_proxy;
192 void set_remove_proxy(bool remove_proxy) {
193 remove_proxy_ = remove_proxy;
196 const ProxyService* proxy_service() const {
197 return proxy_service_;
200 private:
201 bool on_resolve_proxy_called_;
202 bool add_proxy_;
203 bool remove_proxy_;
204 const ProxyService* proxy_service_;
207 // A test network delegate that exercises the OnProxyFallback callback.
208 class TestProxyFallbackNetworkDelegate : public NetworkDelegateImpl {
209 public:
210 TestProxyFallbackNetworkDelegate()
211 : on_proxy_fallback_called_(false),
212 proxy_fallback_net_error_(OK) {
215 void OnProxyFallback(const ProxyServer& proxy_server,
216 int net_error) override {
217 proxy_server_ = proxy_server;
218 proxy_fallback_net_error_ = net_error;
219 on_proxy_fallback_called_ = true;
222 bool on_proxy_fallback_called() const {
223 return on_proxy_fallback_called_;
226 const ProxyServer& proxy_server() const {
227 return proxy_server_;
230 int proxy_fallback_net_error() const {
231 return proxy_fallback_net_error_;
234 private:
235 bool on_proxy_fallback_called_;
236 ProxyServer proxy_server_;
237 int proxy_fallback_net_error_;
240 } // namespace
242 TEST_F(ProxyServiceTest, Direct) {
243 MockAsyncProxyResolver resolver;
244 ProxyService service(
245 new MockProxyConfigService(ProxyConfig::CreateDirect()),
246 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
248 GURL url("http://www.google.com/");
250 ProxyInfo info;
251 TestCompletionCallback callback;
252 BoundTestNetLog log;
253 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
254 NULL, NULL, log.bound());
255 EXPECT_EQ(OK, rv);
256 EXPECT_TRUE(resolver.pending_requests().empty());
258 EXPECT_TRUE(info.is_direct());
259 EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
260 EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
262 // Check the NetLog was filled correctly.
263 TestNetLog::CapturedEntryList entries;
264 log.GetEntries(&entries);
266 EXPECT_EQ(3u, entries.size());
267 EXPECT_TRUE(LogContainsBeginEvent(
268 entries, 0, NetLog::TYPE_PROXY_SERVICE));
269 EXPECT_TRUE(LogContainsEvent(
270 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
271 NetLog::PHASE_NONE));
272 EXPECT_TRUE(LogContainsEndEvent(
273 entries, 2, NetLog::TYPE_PROXY_SERVICE));
276 TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) {
277 ProxyConfig config;
278 config.proxy_rules().ParseFromString("foopy1:8080");
279 config.set_auto_detect(false);
280 config.proxy_rules().bypass_rules.ParseFromString("*.org");
282 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
284 GURL url("http://www.google.com/");
285 GURL bypass_url("http://internet.org");
287 ProxyInfo info;
288 TestCompletionCallback callback;
289 BoundTestNetLog log;
291 // First, warm up the ProxyService.
292 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
293 NULL, NULL, log.bound());
294 EXPECT_EQ(OK, rv);
296 // Verify that network delegate is invoked.
297 TestResolveProxyNetworkDelegate delegate;
298 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
299 &delegate, log.bound());
300 EXPECT_TRUE(delegate.on_resolve_proxy_called());
301 EXPECT_EQ(&service, delegate.proxy_service());
303 // Verify that the NetworkDelegate's behavior is stateless across
304 // invocations of ResolveProxy. Start by having the callback add a proxy
305 // and checking that subsequent requests are not affected.
306 delegate.set_add_proxy(true);
308 // Callback should interpose:
309 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
310 &delegate, log.bound());
311 EXPECT_FALSE(info.is_direct());
312 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com");
313 delegate.set_add_proxy(false);
315 // Check non-bypassed URL:
316 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
317 &delegate, log.bound());
318 EXPECT_FALSE(info.is_direct());
319 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
321 // Check bypassed URL:
322 rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
323 NULL, &delegate, log.bound());
324 EXPECT_TRUE(info.is_direct());
327 TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
328 // Same as OnResolveProxyCallbackAddProxy, but verify that the
329 // NetworkDelegate's behavior is stateless across invocations after it
330 // *removes* a proxy.
331 ProxyConfig config;
332 config.proxy_rules().ParseFromString("foopy1:8080");
333 config.set_auto_detect(false);
334 config.proxy_rules().bypass_rules.ParseFromString("*.org");
336 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
338 GURL url("http://www.google.com/");
339 GURL bypass_url("http://internet.org");
341 ProxyInfo info;
342 TestCompletionCallback callback;
343 BoundTestNetLog log;
345 // First, warm up the ProxyService.
346 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
347 NULL, NULL, log.bound());
348 EXPECT_EQ(OK, rv);
350 TestResolveProxyNetworkDelegate delegate;
351 delegate.set_remove_proxy(true);
353 // Callback should interpose:
354 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
355 &delegate, log.bound());
356 EXPECT_TRUE(info.is_direct());
357 delegate.set_remove_proxy(false);
359 // Check non-bypassed URL:
360 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
361 &delegate, log.bound());
362 EXPECT_FALSE(info.is_direct());
363 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
365 // Check bypassed URL:
366 rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
367 NULL, &delegate, log.bound());
368 EXPECT_TRUE(info.is_direct());
371 TEST_F(ProxyServiceTest, PAC) {
372 MockProxyConfigService* config_service =
373 new MockProxyConfigService("http://foopy/proxy.pac");
375 MockAsyncProxyResolver resolver;
377 ProxyService service(
378 config_service,
379 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
381 GURL url("http://www.google.com/");
383 ProxyInfo info;
384 TestCompletionCallback callback;
385 ProxyService::PacRequest* request;
386 BoundTestNetLog log;
388 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
389 &request, NULL, log.bound());
390 EXPECT_EQ(ERR_IO_PENDING, rv);
392 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request));
394 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
395 resolver.pending_set_pac_script_request()->script_data()->url());
396 resolver.pending_set_pac_script_request()->CompleteNow(OK);
398 ASSERT_EQ(1u, resolver.pending_requests().size());
399 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
401 // Set the result in proxy resolver.
402 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy");
403 resolver.pending_requests()[0]->CompleteNow(OK);
405 EXPECT_EQ(OK, callback.WaitForResult());
406 EXPECT_FALSE(info.is_direct());
407 EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
408 EXPECT_TRUE(info.did_use_pac_script());
410 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
411 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
412 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
414 // Check the NetLog was filled correctly.
415 TestNetLog::CapturedEntryList entries;
416 log.GetEntries(&entries);
418 EXPECT_EQ(5u, entries.size());
419 EXPECT_TRUE(LogContainsBeginEvent(
420 entries, 0, NetLog::TYPE_PROXY_SERVICE));
421 EXPECT_TRUE(LogContainsBeginEvent(
422 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
423 EXPECT_TRUE(LogContainsEndEvent(
424 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
425 EXPECT_TRUE(LogContainsEndEvent(
426 entries, 4, NetLog::TYPE_PROXY_SERVICE));
429 // Test that the proxy resolver does not see the URL's username/password
430 // or its reference section.
431 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) {
432 MockProxyConfigService* config_service =
433 new MockProxyConfigService("http://foopy/proxy.pac");
435 MockAsyncProxyResolver resolver;
437 ProxyService service(
438 config_service,
439 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
441 GURL url("http://username:password@www.google.com/?ref#hash#hash");
443 ProxyInfo info;
444 TestCompletionCallback callback;
445 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
446 NULL, NULL, BoundNetLog());
447 EXPECT_EQ(ERR_IO_PENDING, rv);
449 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
450 resolver.pending_set_pac_script_request()->script_data()->url());
451 resolver.pending_set_pac_script_request()->CompleteNow(OK);
453 ASSERT_EQ(1u, resolver.pending_requests().size());
454 // The URL should have been simplified, stripping the username/password/hash.
455 EXPECT_EQ(GURL("http://www.google.com/?ref"),
456 resolver.pending_requests()[0]->url());
458 // We end here without ever completing the request -- destruction of
459 // ProxyService will cancel the outstanding request.
462 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
463 MockProxyConfigService* config_service =
464 new MockProxyConfigService("http://foopy/proxy.pac");
465 MockAsyncProxyResolver resolver;
467 ProxyService service(
468 config_service,
469 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
471 GURL url("http://www.google.com/");
473 ProxyInfo info;
474 TestCompletionCallback callback1;
475 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
476 NULL, NULL, BoundNetLog());
477 EXPECT_EQ(ERR_IO_PENDING, rv);
479 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
480 resolver.pending_set_pac_script_request()->script_data()->url());
481 resolver.pending_set_pac_script_request()->CompleteNow(OK);
483 ASSERT_EQ(1u, resolver.pending_requests().size());
484 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
486 // Set the result in proxy resolver.
487 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
488 resolver.pending_requests()[0]->CompleteNow(OK);
490 EXPECT_EQ(OK, callback1.WaitForResult());
491 EXPECT_FALSE(info.is_direct());
492 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
493 EXPECT_TRUE(info.did_use_pac_script());
495 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
496 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
497 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
499 // Now, imagine that connecting to foopy:8080 fails: there is nothing
500 // left to fallback to, since our proxy list was NOT terminated by
501 // DIRECT.
502 NetworkDelegateImpl network_delegate;
503 TestCompletionCallback callback2;
504 ProxyServer expected_proxy_server = info.proxy_server();
505 rv = service.ReconsiderProxyAfterError(
506 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
507 callback2.callback(), NULL, &network_delegate, BoundNetLog());
508 // ReconsiderProxyAfterError returns error indicating nothing left.
509 EXPECT_EQ(ERR_FAILED, rv);
510 EXPECT_TRUE(info.is_empty());
513 // Test that if the execution of the PAC script fails (i.e. javascript runtime
514 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
515 TEST_F(ProxyServiceTest, PAC_RuntimeError) {
516 MockProxyConfigService* config_service =
517 new MockProxyConfigService("http://foopy/proxy.pac");
518 MockAsyncProxyResolver resolver;
520 ProxyService service(
521 config_service,
522 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
524 GURL url("http://this-causes-js-error/");
526 ProxyInfo info;
527 TestCompletionCallback callback1;
528 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
529 NULL, NULL, BoundNetLog());
530 EXPECT_EQ(ERR_IO_PENDING, rv);
532 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
533 resolver.pending_set_pac_script_request()->script_data()->url());
534 resolver.pending_set_pac_script_request()->CompleteNow(OK);
536 ASSERT_EQ(1u, resolver.pending_requests().size());
537 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
539 // Simulate a failure in the PAC executor.
540 resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
542 EXPECT_EQ(OK, callback1.WaitForResult());
544 // Since the PAC script was non-mandatory, we should have fallen-back to
545 // DIRECT.
546 EXPECT_TRUE(info.is_direct());
547 EXPECT_TRUE(info.did_use_pac_script());
548 EXPECT_EQ(1, info.config_id());
550 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
551 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
552 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
555 // The proxy list could potentially contain the DIRECT fallback choice
556 // in a location other than the very end of the list, and could even
557 // specify it multiple times.
559 // This is not a typical usage, but we will obey it.
560 // (If we wanted to disallow this type of input, the right place to
561 // enforce it would be in parsing the PAC result string).
563 // This test will use the PAC result string:
565 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
567 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
568 // then foobar:20, and then give up and error.
570 // The important check of this test is to make sure that DIRECT is not somehow
571 // cached as being a bad proxy.
572 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
573 MockProxyConfigService* config_service =
574 new MockProxyConfigService("http://foopy/proxy.pac");
575 MockAsyncProxyResolver resolver;
577 ProxyService service(
578 config_service,
579 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
581 GURL url("http://www.google.com/");
583 ProxyInfo info;
584 TestCompletionCallback callback1;
585 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
586 NULL, NULL, BoundNetLog());
587 EXPECT_EQ(ERR_IO_PENDING, rv);
589 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
590 resolver.pending_set_pac_script_request()->script_data()->url());
591 resolver.pending_set_pac_script_request()->CompleteNow(OK);
593 ASSERT_EQ(1u, resolver.pending_requests().size());
594 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
596 // Set the result in proxy resolver.
597 resolver.pending_requests()[0]->results()->UsePacString(
598 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
599 resolver.pending_requests()[0]->CompleteNow(OK);
601 EXPECT_EQ(OK, callback1.WaitForResult());
602 EXPECT_TRUE(info.is_direct());
604 // Fallback 1.
605 TestCompletionCallback callback2;
606 rv = service.ReconsiderProxyAfterError(
607 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
608 callback2.callback(), NULL, NULL, BoundNetLog());
609 EXPECT_EQ(OK, rv);
610 EXPECT_FALSE(info.is_direct());
611 EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
613 // Fallback 2.
614 NetworkDelegateImpl network_delegate;
615 ProxyServer expected_proxy_server3 = info.proxy_server();
616 TestCompletionCallback callback3;
617 rv = service.ReconsiderProxyAfterError(
618 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
619 callback3.callback(), NULL, &network_delegate, BoundNetLog());
620 EXPECT_EQ(OK, rv);
621 EXPECT_TRUE(info.is_direct());
623 // Fallback 3.
624 ProxyServer expected_proxy_server4 = info.proxy_server();
625 TestCompletionCallback callback4;
626 rv = service.ReconsiderProxyAfterError(
627 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
628 callback4.callback(), NULL, &network_delegate, BoundNetLog());
629 EXPECT_EQ(OK, rv);
630 EXPECT_FALSE(info.is_direct());
631 EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
633 // Fallback 4 -- Nothing to fall back to!
634 ProxyServer expected_proxy_server5 = info.proxy_server();
635 TestCompletionCallback callback5;
636 rv = service.ReconsiderProxyAfterError(
637 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
638 callback5.callback(), NULL, &network_delegate, BoundNetLog());
639 EXPECT_EQ(ERR_FAILED, rv);
640 EXPECT_TRUE(info.is_empty());
643 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
644 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
645 // to ProxyInfo after the proxy is resolved via a PAC script.
646 ProxyConfig config =
647 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
648 config.set_source(PROXY_CONFIG_SOURCE_TEST);
650 MockProxyConfigService* config_service = new MockProxyConfigService(config);
651 MockAsyncProxyResolver resolver;
652 ProxyService service(
653 config_service,
654 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
656 // Resolve something.
657 GURL url("http://www.google.com/");
658 ProxyInfo info;
659 TestCompletionCallback callback;
660 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
661 NULL, NULL, BoundNetLog());
662 ASSERT_EQ(ERR_IO_PENDING, rv);
663 resolver.pending_set_pac_script_request()->CompleteNow(OK);
664 ASSERT_EQ(1u, resolver.pending_requests().size());
666 // Set the result in proxy resolver.
667 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy");
668 resolver.pending_requests()[0]->CompleteNow(OK);
670 EXPECT_EQ(OK, callback.WaitForResult());
671 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
672 EXPECT_TRUE(info.did_use_pac_script());
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());
679 TEST_F(ProxyServiceTest, ProxyResolverFails) {
680 // Test what happens when the ProxyResolver fails. The download and setting
681 // of the PAC script have already succeeded, so this corresponds with a
682 // javascript runtime error while calling FindProxyForURL().
684 MockProxyConfigService* config_service =
685 new MockProxyConfigService("http://foopy/proxy.pac");
687 MockAsyncProxyResolver resolver;
689 ProxyService service(
690 config_service,
691 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
693 // Start first resolve request.
694 GURL url("http://www.google.com/");
695 ProxyInfo info;
696 TestCompletionCallback callback1;
697 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
698 NULL, NULL, BoundNetLog());
699 EXPECT_EQ(ERR_IO_PENDING, rv);
701 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
702 resolver.pending_set_pac_script_request()->script_data()->url());
703 resolver.pending_set_pac_script_request()->CompleteNow(OK);
705 ASSERT_EQ(1u, resolver.pending_requests().size());
706 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
708 // Fail the first resolve request in MockAsyncProxyResolver.
709 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
711 // Although the proxy resolver failed the request, ProxyService implicitly
712 // falls-back to DIRECT.
713 EXPECT_EQ(OK, callback1.WaitForResult());
714 EXPECT_TRUE(info.is_direct());
716 // Failed PAC executions still have proxy resolution times.
717 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
718 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
719 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
721 // The second resolve request will try to run through the proxy resolver,
722 // regardless of whether the first request failed in it.
723 TestCompletionCallback callback2;
724 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
725 NULL, BoundNetLog());
726 EXPECT_EQ(ERR_IO_PENDING, rv);
728 ASSERT_EQ(1u, resolver.pending_requests().size());
729 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
731 // This time we will have the resolver succeed (perhaps the PAC script has
732 // a dependency on the current time).
733 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
734 resolver.pending_requests()[0]->CompleteNow(OK);
736 EXPECT_EQ(OK, callback2.WaitForResult());
737 EXPECT_FALSE(info.is_direct());
738 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
741 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
742 // Test what happens when the ProxyScriptResolver fails to download a
743 // mandatory PAC script.
745 ProxyConfig config(
746 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
747 config.set_pac_mandatory(true);
749 MockProxyConfigService* config_service = new MockProxyConfigService(config);
751 MockAsyncProxyResolver resolver;
753 ProxyService service(
754 config_service,
755 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
757 // Start first resolve request.
758 GURL url("http://www.google.com/");
759 ProxyInfo info;
760 TestCompletionCallback callback1;
761 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
762 NULL, NULL, BoundNetLog());
763 EXPECT_EQ(ERR_IO_PENDING, rv);
765 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
766 resolver.pending_set_pac_script_request()->script_data()->url());
767 resolver.pending_set_pac_script_request()->CompleteNow(ERR_FAILED);
769 ASSERT_EQ(0u, resolver.pending_requests().size());
770 // As the proxy resolver failed the request and is configured for a mandatory
771 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
772 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
773 callback1.WaitForResult());
774 EXPECT_FALSE(info.is_direct());
776 // As the proxy resolver failed the request and is configured for a mandatory
777 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
778 TestCompletionCallback callback2;
779 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
780 NULL, BoundNetLog());
781 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
782 EXPECT_FALSE(info.is_direct());
785 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
786 // Test what happens when the ProxyResolver fails that is configured to use a
787 // mandatory PAC script. The download of the PAC script has already
788 // succeeded but the PAC script contains no valid javascript.
790 ProxyConfig config(
791 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
792 config.set_pac_mandatory(true);
794 MockProxyConfigService* config_service = new MockProxyConfigService(config);
796 MockAsyncProxyResolverExpectsBytes resolver;
798 ProxyService service(
799 config_service,
800 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
802 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
803 DhcpProxyScriptFetcher* dhcp_fetcher = new DoNothingDhcpProxyScriptFetcher();
804 service.SetProxyScriptFetchers(fetcher, dhcp_fetcher);
806 // Start resolve request.
807 GURL url("http://www.google.com/");
808 ProxyInfo info;
809 TestCompletionCallback callback;
810 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
811 NULL, NULL, BoundNetLog());
812 EXPECT_EQ(ERR_IO_PENDING, rv);
814 // Check that nothing has been sent to the proxy resolver yet.
815 ASSERT_EQ(0u, resolver.pending_requests().size());
817 // Downloading the PAC script succeeds.
818 EXPECT_TRUE(fetcher->has_pending_request());
819 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
820 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
822 EXPECT_FALSE(fetcher->has_pending_request());
823 ASSERT_EQ(0u, resolver.pending_requests().size());
825 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
826 // mandatory for this configuration, the ProxyService must not implicitly
827 // fall-back to DIRECT.
828 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
829 callback.WaitForResult());
830 EXPECT_FALSE(info.is_direct());
833 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
834 // Test what happens when the ProxyResolver fails that is configured to use a
835 // mandatory PAC script. The download and setting of the PAC script have
836 // already succeeded, so this corresponds with a javascript runtime error
837 // while calling FindProxyForURL().
839 ProxyConfig config(
840 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
841 config.set_pac_mandatory(true);
843 MockProxyConfigService* config_service = new MockProxyConfigService(config);
845 MockAsyncProxyResolver resolver;
847 ProxyService service(
848 config_service,
849 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
851 // Start first resolve request.
852 GURL url("http://www.google.com/");
853 ProxyInfo info;
854 TestCompletionCallback callback1;
855 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
856 NULL, NULL, BoundNetLog());
857 EXPECT_EQ(ERR_IO_PENDING, rv);
859 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
860 resolver.pending_set_pac_script_request()->script_data()->url());
861 resolver.pending_set_pac_script_request()->CompleteNow(OK);
863 ASSERT_EQ(1u, resolver.pending_requests().size());
864 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
866 // Fail the first resolve request in MockAsyncProxyResolver.
867 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
869 // As the proxy resolver failed the request and is configured for a mandatory
870 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
871 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
872 callback1.WaitForResult());
873 EXPECT_FALSE(info.is_direct());
875 // The second resolve request will try to run through the proxy resolver,
876 // regardless of whether the first request failed in it.
877 TestCompletionCallback callback2;
878 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
879 NULL, BoundNetLog());
880 EXPECT_EQ(ERR_IO_PENDING, rv);
882 ASSERT_EQ(1u, resolver.pending_requests().size());
883 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
885 // This time we will have the resolver succeed (perhaps the PAC script has
886 // a dependency on the current time).
887 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
888 resolver.pending_requests()[0]->CompleteNow(OK);
890 EXPECT_EQ(OK, callback2.WaitForResult());
891 EXPECT_FALSE(info.is_direct());
892 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
895 TEST_F(ProxyServiceTest, ProxyFallback) {
896 // Test what happens when we specify multiple proxy servers and some of them
897 // are bad.
899 MockProxyConfigService* config_service =
900 new MockProxyConfigService("http://foopy/proxy.pac");
902 MockAsyncProxyResolver resolver;
904 ProxyService service(
905 config_service,
906 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
908 GURL url("http://www.google.com/");
910 // Get the proxy information.
911 ProxyInfo info;
912 TestCompletionCallback callback1;
913 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
914 NULL, NULL, BoundNetLog());
915 EXPECT_EQ(ERR_IO_PENDING, rv);
917 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
918 resolver.pending_set_pac_script_request()->script_data()->url());
919 resolver.pending_set_pac_script_request()->CompleteNow(OK);
921 ASSERT_EQ(1u, resolver.pending_requests().size());
922 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
924 // Set the result in proxy resolver.
925 resolver.pending_requests()[0]->results()->UseNamedProxy(
926 "foopy1:8080;foopy2:9090");
927 resolver.pending_requests()[0]->CompleteNow(OK);
929 // The first item is valid.
930 EXPECT_EQ(OK, callback1.WaitForResult());
931 EXPECT_FALSE(info.is_direct());
932 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
934 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
935 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
936 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
937 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
938 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
940 // Fake an error on the proxy.
941 TestCompletionCallback callback2;
942 rv = service.ReconsiderProxyAfterError(
943 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
944 callback2.callback(), NULL, NULL, BoundNetLog());
945 EXPECT_EQ(OK, rv);
947 // Proxy times should not have been modified by fallback.
948 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
949 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
951 // The second proxy should be specified.
952 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
953 // Report back that the second proxy worked. This will globally mark the
954 // first proxy as bad.
955 TestProxyFallbackNetworkDelegate test_delegate;
956 service.ReportSuccess(info, &test_delegate);
957 EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI());
958 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
959 test_delegate.proxy_fallback_net_error());
961 TestCompletionCallback callback3;
962 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback3.callback(), NULL,
963 NULL, BoundNetLog());
964 EXPECT_EQ(ERR_IO_PENDING, rv);
966 ASSERT_EQ(1u, resolver.pending_requests().size());
967 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
969 // Set the result in proxy resolver -- the second result is already known
970 // to be bad, so we will not try to use it initially.
971 resolver.pending_requests()[0]->results()->UseNamedProxy(
972 "foopy3:7070;foopy1:8080;foopy2:9090");
973 resolver.pending_requests()[0]->CompleteNow(OK);
975 EXPECT_EQ(OK, callback3.WaitForResult());
976 EXPECT_FALSE(info.is_direct());
977 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
979 // Proxy times should have been updated, so get them again.
980 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
981 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
982 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
983 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
984 proxy_resolve_start_time = info.proxy_resolve_start_time();
985 proxy_resolve_end_time = info.proxy_resolve_end_time();
987 // We fake another error. It should now try the third one.
988 TestCompletionCallback callback4;
989 rv = service.ReconsiderProxyAfterError(
990 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
991 callback4.callback(), NULL, NULL, BoundNetLog());
992 EXPECT_EQ(OK, rv);
993 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
995 // We fake another error. At this point we have tried all of the
996 // proxy servers we thought were valid; next we try the proxy server
997 // that was in our bad proxies map (foopy1:8080).
998 TestCompletionCallback callback5;
999 rv = service.ReconsiderProxyAfterError(
1000 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1001 callback5.callback(), NULL, NULL, BoundNetLog());
1002 EXPECT_EQ(OK, rv);
1003 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1005 // Fake another error, the last proxy is gone, the list should now be empty,
1006 // so there is nothing left to try.
1007 TestCompletionCallback callback6;
1008 rv = service.ReconsiderProxyAfterError(
1009 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1010 callback6.callback(), NULL, NULL, BoundNetLog());
1011 EXPECT_EQ(ERR_FAILED, rv);
1012 EXPECT_FALSE(info.is_direct());
1013 EXPECT_TRUE(info.is_empty());
1015 // Proxy times should not have been modified by fallback.
1016 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1017 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1019 // Look up proxies again
1020 TestCompletionCallback callback7;
1021 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback7.callback(), NULL,
1022 NULL, BoundNetLog());
1023 EXPECT_EQ(ERR_IO_PENDING, rv);
1025 ASSERT_EQ(1u, resolver.pending_requests().size());
1026 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1028 // This time, the first 3 results have been found to be bad, but only the
1029 // first proxy has been confirmed ...
1030 resolver.pending_requests()[0]->results()->UseNamedProxy(
1031 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
1032 resolver.pending_requests()[0]->CompleteNow(OK);
1034 // ... therefore, we should see the second proxy first.
1035 EXPECT_EQ(OK, callback7.WaitForResult());
1036 EXPECT_FALSE(info.is_direct());
1037 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
1039 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1040 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1041 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1042 // TODO(nsylvain): Test that the proxy can be retried after the delay.
1045 // This test is similar to ProxyFallback, but this time we have an explicit
1046 // fallback choice to DIRECT.
1047 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
1048 MockProxyConfigService* config_service =
1049 new MockProxyConfigService("http://foopy/proxy.pac");
1051 MockAsyncProxyResolver resolver;
1053 ProxyService service(
1054 config_service,
1055 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1057 GURL url("http://www.google.com/");
1059 // Get the proxy information.
1060 ProxyInfo info;
1061 TestCompletionCallback callback1;
1062 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1063 NULL, NULL, BoundNetLog());
1064 EXPECT_EQ(ERR_IO_PENDING, rv);
1066 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1067 resolver.pending_set_pac_script_request()->script_data()->url());
1068 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1070 ASSERT_EQ(1u, resolver.pending_requests().size());
1071 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1073 // Set the result in proxy resolver.
1074 resolver.pending_requests()[0]->results()->UsePacString(
1075 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
1076 resolver.pending_requests()[0]->CompleteNow(OK);
1078 // Get the first result.
1079 EXPECT_EQ(OK, callback1.WaitForResult());
1080 EXPECT_FALSE(info.is_direct());
1081 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1083 // Fake an error on the proxy.
1084 TestCompletionCallback callback2;
1085 rv = service.ReconsiderProxyAfterError(
1086 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1087 callback2.callback(), NULL, NULL, BoundNetLog());
1088 EXPECT_EQ(OK, rv);
1090 // Now we get back the second proxy.
1091 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1093 // Fake an error on this proxy as well.
1094 TestCompletionCallback callback3;
1095 rv = service.ReconsiderProxyAfterError(
1096 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1097 callback3.callback(), NULL, NULL, BoundNetLog());
1098 EXPECT_EQ(OK, rv);
1100 // Finally, we get back DIRECT.
1101 EXPECT_TRUE(info.is_direct());
1103 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1104 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1105 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1107 // Now we tell the proxy service that even DIRECT failed.
1108 TestCompletionCallback callback4;
1109 rv = service.ReconsiderProxyAfterError(
1110 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1111 callback4.callback(), NULL, NULL, BoundNetLog());
1112 // There was nothing left to try after DIRECT, so we are out of
1113 // choices.
1114 EXPECT_EQ(ERR_FAILED, rv);
1117 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
1118 // Test proxy failover when new settings are available.
1120 MockProxyConfigService* config_service =
1121 new MockProxyConfigService("http://foopy/proxy.pac");
1123 MockAsyncProxyResolver resolver;
1125 ProxyService service(
1126 config_service,
1127 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1129 GURL url("http://www.google.com/");
1131 // Get the proxy information.
1132 ProxyInfo info;
1133 TestCompletionCallback callback1;
1134 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1135 NULL, NULL, BoundNetLog());
1136 EXPECT_EQ(ERR_IO_PENDING, rv);
1138 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1139 resolver.pending_set_pac_script_request()->script_data()->url());
1140 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1142 ASSERT_EQ(1u, resolver.pending_requests().size());
1143 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1145 // Set the result in proxy resolver.
1146 resolver.pending_requests()[0]->results()->UseNamedProxy(
1147 "foopy1:8080;foopy2:9090");
1148 resolver.pending_requests()[0]->CompleteNow(OK);
1150 // The first item is valid.
1151 EXPECT_EQ(OK, callback1.WaitForResult());
1152 EXPECT_FALSE(info.is_direct());
1153 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1155 // Fake an error on the proxy, and also a new configuration on the proxy.
1156 config_service->SetConfig(
1157 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
1159 TestCompletionCallback callback2;
1160 rv = service.ReconsiderProxyAfterError(
1161 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1162 callback2.callback(), NULL, NULL, BoundNetLog());
1163 EXPECT_EQ(ERR_IO_PENDING, rv);
1165 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
1166 resolver.pending_set_pac_script_request()->script_data()->url());
1167 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1169 ASSERT_EQ(1u, resolver.pending_requests().size());
1170 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1172 resolver.pending_requests()[0]->results()->UseNamedProxy(
1173 "foopy1:8080;foopy2:9090");
1174 resolver.pending_requests()[0]->CompleteNow(OK);
1176 // The first proxy is still there since the configuration changed.
1177 EXPECT_EQ(OK, callback2.WaitForResult());
1178 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1180 // We fake another error. It should now ignore the first one.
1181 TestCompletionCallback callback3;
1182 rv = service.ReconsiderProxyAfterError(
1183 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1184 callback3.callback(), NULL, NULL, BoundNetLog());
1185 EXPECT_EQ(OK, rv);
1186 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1188 // We simulate a new configuration.
1189 config_service->SetConfig(
1190 ProxyConfig::CreateFromCustomPacURL(
1191 GURL("http://foopy-new2/proxy.pac")));
1193 // We fake another error. It should go back to the first proxy.
1194 TestCompletionCallback callback4;
1195 rv = service.ReconsiderProxyAfterError(
1196 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1197 callback4.callback(), NULL, NULL, BoundNetLog());
1198 EXPECT_EQ(ERR_IO_PENDING, rv);
1200 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
1201 resolver.pending_set_pac_script_request()->script_data()->url());
1202 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1204 ASSERT_EQ(1u, resolver.pending_requests().size());
1205 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1207 resolver.pending_requests()[0]->results()->UseNamedProxy(
1208 "foopy1:8080;foopy2:9090");
1209 resolver.pending_requests()[0]->CompleteNow(OK);
1211 EXPECT_EQ(OK, callback4.WaitForResult());
1212 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1214 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1215 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1216 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1219 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
1220 // Test proxy failover when the configuration is bad.
1222 MockProxyConfigService* config_service =
1223 new MockProxyConfigService("http://foopy/proxy.pac");
1225 MockAsyncProxyResolver resolver;
1227 ProxyService service(
1228 config_service,
1229 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1231 GURL url("http://www.google.com/");
1233 // Get the proxy information.
1234 ProxyInfo info;
1235 TestCompletionCallback callback1;
1236 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1237 NULL, NULL, BoundNetLog());
1238 EXPECT_EQ(ERR_IO_PENDING, rv);
1240 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1241 resolver.pending_set_pac_script_request()->script_data()->url());
1242 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1243 ASSERT_EQ(1u, resolver.pending_requests().size());
1244 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1246 resolver.pending_requests()[0]->results()->UseNamedProxy(
1247 "foopy1:8080;foopy2:9090");
1248 resolver.pending_requests()[0]->CompleteNow(OK);
1250 // The first item is valid.
1251 EXPECT_EQ(OK, callback1.WaitForResult());
1252 EXPECT_FALSE(info.is_direct());
1253 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1255 // Fake a proxy error.
1256 TestCompletionCallback callback2;
1257 rv = service.ReconsiderProxyAfterError(
1258 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1259 callback2.callback(), NULL, NULL, BoundNetLog());
1260 EXPECT_EQ(OK, rv);
1262 // The first proxy is ignored, and the second one is selected.
1263 EXPECT_FALSE(info.is_direct());
1264 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1266 // Fake a PAC failure.
1267 ProxyInfo info2;
1268 TestCompletionCallback callback3;
1269 rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
1270 NULL, NULL, BoundNetLog());
1271 EXPECT_EQ(ERR_IO_PENDING, rv);
1273 ASSERT_EQ(1u, resolver.pending_requests().size());
1274 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1276 // This simulates a javascript runtime error in the PAC script.
1277 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1279 // Although the resolver failed, the ProxyService will implicitly fall-back
1280 // to a DIRECT connection.
1281 EXPECT_EQ(OK, callback3.WaitForResult());
1282 EXPECT_TRUE(info2.is_direct());
1283 EXPECT_FALSE(info2.is_empty());
1285 // The PAC script will work properly next time and successfully return a
1286 // proxy list. Since we have not marked the configuration as bad, it should
1287 // "just work" the next time we call it.
1288 ProxyInfo info3;
1289 TestCompletionCallback callback4;
1290 rv = service.ReconsiderProxyAfterError(
1291 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
1292 callback4.callback(), NULL, NULL, BoundNetLog());
1293 EXPECT_EQ(ERR_IO_PENDING, rv);
1295 ASSERT_EQ(1u, resolver.pending_requests().size());
1296 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1298 resolver.pending_requests()[0]->results()->UseNamedProxy(
1299 "foopy1:8080;foopy2:9090");
1300 resolver.pending_requests()[0]->CompleteNow(OK);
1302 // The first proxy is not there since the it was added to the bad proxies
1303 // list by the earlier ReconsiderProxyAfterError().
1304 EXPECT_EQ(OK, callback4.WaitForResult());
1305 EXPECT_FALSE(info3.is_direct());
1306 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1308 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1309 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1310 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1313 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
1314 // Test proxy failover when the configuration is bad.
1316 ProxyConfig config(
1317 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1319 config.set_pac_mandatory(true);
1320 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1322 MockAsyncProxyResolver resolver;
1324 ProxyService service(
1325 config_service,
1326 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1328 GURL url("http://www.google.com/");
1330 // Get the proxy information.
1331 ProxyInfo info;
1332 TestCompletionCallback callback1;
1333 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1334 NULL, NULL, BoundNetLog());
1335 EXPECT_EQ(ERR_IO_PENDING, rv);
1337 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1338 resolver.pending_set_pac_script_request()->script_data()->url());
1339 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1340 ASSERT_EQ(1u, resolver.pending_requests().size());
1341 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1343 resolver.pending_requests()[0]->results()->UseNamedProxy(
1344 "foopy1:8080;foopy2:9090");
1345 resolver.pending_requests()[0]->CompleteNow(OK);
1347 // The first item is valid.
1348 EXPECT_EQ(OK, callback1.WaitForResult());
1349 EXPECT_FALSE(info.is_direct());
1350 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1352 // Fake a proxy error.
1353 TestCompletionCallback callback2;
1354 rv = service.ReconsiderProxyAfterError(
1355 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1356 callback2.callback(), NULL, NULL, BoundNetLog());
1357 EXPECT_EQ(OK, rv);
1359 // The first proxy is ignored, and the second one is selected.
1360 EXPECT_FALSE(info.is_direct());
1361 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1363 // Fake a PAC failure.
1364 ProxyInfo info2;
1365 TestCompletionCallback callback3;
1366 rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
1367 NULL, NULL, BoundNetLog());
1368 EXPECT_EQ(ERR_IO_PENDING, rv);
1370 ASSERT_EQ(1u, resolver.pending_requests().size());
1371 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1373 // This simulates a javascript runtime error in the PAC script.
1374 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1376 // Although the resolver failed, the ProxyService will NOT fall-back
1377 // to a DIRECT connection as it is configured as mandatory.
1378 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1379 callback3.WaitForResult());
1380 EXPECT_FALSE(info2.is_direct());
1381 EXPECT_TRUE(info2.is_empty());
1383 // The PAC script will work properly next time and successfully return a
1384 // proxy list. Since we have not marked the configuration as bad, it should
1385 // "just work" the next time we call it.
1386 ProxyInfo info3;
1387 TestCompletionCallback callback4;
1388 rv = service.ReconsiderProxyAfterError(
1389 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
1390 callback4.callback(), NULL, NULL, BoundNetLog());
1391 EXPECT_EQ(ERR_IO_PENDING, rv);
1393 ASSERT_EQ(1u, resolver.pending_requests().size());
1394 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1396 resolver.pending_requests()[0]->results()->UseNamedProxy(
1397 "foopy1:8080;foopy2:9090");
1398 resolver.pending_requests()[0]->CompleteNow(OK);
1400 // The first proxy is not there since the it was added to the bad proxies
1401 // list by the earlier ReconsiderProxyAfterError().
1402 EXPECT_EQ(OK, callback4.WaitForResult());
1403 EXPECT_FALSE(info3.is_direct());
1404 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1407 TEST_F(ProxyServiceTest, ProxyBypassList) {
1408 // Test that the proxy bypass rules are consulted.
1410 TestCompletionCallback callback[2];
1411 ProxyInfo info[2];
1412 ProxyConfig config;
1413 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1414 config.set_auto_detect(false);
1415 config.proxy_rules().bypass_rules.ParseFromString("*.org");
1417 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1419 int rv;
1420 GURL url1("http://www.webkit.org");
1421 GURL url2("http://www.webkit.com");
1423 // Request for a .org domain should bypass proxy.
1424 rv = service.ResolveProxy(url1, LOAD_NORMAL, &info[0], callback[0].callback(),
1425 NULL, NULL, BoundNetLog());
1426 EXPECT_EQ(OK, rv);
1427 EXPECT_TRUE(info[0].is_direct());
1429 // Request for a .com domain hits the proxy.
1430 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info[1], callback[1].callback(),
1431 NULL, NULL, BoundNetLog());
1432 EXPECT_EQ(OK, rv);
1433 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
1437 TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
1438 ProxyConfig config;
1439 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1440 config.set_auto_detect(false);
1442 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1443 GURL test_url("http://www.msn.com");
1444 ProxyInfo info;
1445 TestCompletionCallback callback;
1446 int rv =
1447 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1448 NULL, NULL, BoundNetLog());
1449 EXPECT_EQ(OK, rv);
1450 EXPECT_FALSE(info.is_direct());
1451 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1454 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1455 GURL test_url("ftp://ftp.google.com");
1456 ProxyInfo info;
1457 TestCompletionCallback callback;
1458 int rv =
1459 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1460 NULL, NULL, BoundNetLog());
1461 EXPECT_EQ(OK, rv);
1462 EXPECT_TRUE(info.is_direct());
1463 EXPECT_EQ("direct://", info.proxy_server().ToURI());
1466 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1467 GURL test_url("https://webbranch.techcu.com");
1468 ProxyInfo info;
1469 TestCompletionCallback callback;
1470 int rv =
1471 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1472 NULL, NULL, BoundNetLog());
1473 EXPECT_EQ(OK, rv);
1474 EXPECT_FALSE(info.is_direct());
1475 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
1478 config.proxy_rules().ParseFromString("foopy1:8080");
1479 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1480 GURL test_url("http://www.microsoft.com");
1481 ProxyInfo info;
1482 TestCompletionCallback callback;
1483 int rv =
1484 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1485 NULL, NULL, BoundNetLog());
1486 EXPECT_EQ(OK, rv);
1487 EXPECT_FALSE(info.is_direct());
1488 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1492 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
1493 // Test that the proxy config source is set correctly when resolving proxies
1494 // using manual proxy rules. Namely, the config source should only be set if
1495 // any of the rules were applied.
1497 ProxyConfig config;
1498 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1499 config.proxy_rules().ParseFromString("https=foopy2:8080");
1500 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1501 GURL test_url("http://www.google.com");
1502 ProxyInfo info;
1503 TestCompletionCallback callback;
1504 int rv =
1505 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1506 NULL, NULL, BoundNetLog());
1507 ASSERT_EQ(OK, rv);
1508 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1509 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1512 ProxyConfig config;
1513 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1514 config.proxy_rules().ParseFromString("https=foopy2:8080");
1515 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1516 GURL test_url("https://www.google.com");
1517 ProxyInfo info;
1518 TestCompletionCallback callback;
1519 int rv =
1520 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1521 NULL, NULL, BoundNetLog());
1522 ASSERT_EQ(OK, rv);
1523 // Used the HTTPS proxy. So source should be TEST.
1524 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1527 ProxyConfig config;
1528 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1529 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1530 GURL test_url("http://www.google.com");
1531 ProxyInfo info;
1532 TestCompletionCallback callback;
1533 int rv =
1534 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1535 NULL, NULL, BoundNetLog());
1536 ASSERT_EQ(OK, rv);
1537 // ProxyConfig is empty. Source should still be TEST.
1538 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1542 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1543 // fall back to the SOCKS proxy.
1544 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
1545 ProxyConfig config;
1546 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1547 config.set_auto_detect(false);
1548 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
1549 config.proxy_rules().type);
1552 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1553 GURL test_url("http://www.msn.com");
1554 ProxyInfo info;
1555 TestCompletionCallback callback;
1556 int rv =
1557 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1558 NULL, NULL, BoundNetLog());
1559 EXPECT_EQ(OK, rv);
1560 EXPECT_FALSE(info.is_direct());
1561 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1564 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1565 GURL test_url("ftp://ftp.google.com");
1566 ProxyInfo info;
1567 TestCompletionCallback callback;
1568 int rv =
1569 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1570 NULL, NULL, BoundNetLog());
1571 EXPECT_EQ(OK, rv);
1572 EXPECT_FALSE(info.is_direct());
1573 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1576 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1577 GURL test_url("https://webbranch.techcu.com");
1578 ProxyInfo info;
1579 TestCompletionCallback callback;
1580 int rv =
1581 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1582 NULL, NULL, BoundNetLog());
1583 EXPECT_EQ(OK, rv);
1584 EXPECT_FALSE(info.is_direct());
1585 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1588 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1589 GURL test_url("unknown://www.microsoft.com");
1590 ProxyInfo info;
1591 TestCompletionCallback callback;
1592 int rv =
1593 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1594 NULL, NULL, BoundNetLog());
1595 EXPECT_EQ(OK, rv);
1596 EXPECT_FALSE(info.is_direct());
1597 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1601 // Test cancellation of an in-progress request.
1602 TEST_F(ProxyServiceTest, CancelInProgressRequest) {
1603 MockProxyConfigService* config_service =
1604 new MockProxyConfigService("http://foopy/proxy.pac");
1606 MockAsyncProxyResolver resolver;
1608 ProxyService service(
1609 config_service,
1610 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1612 // Start 3 requests.
1614 ProxyInfo info1;
1615 TestCompletionCallback callback1;
1616 int rv =
1617 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1618 callback1.callback(), NULL, NULL, BoundNetLog());
1619 EXPECT_EQ(ERR_IO_PENDING, rv);
1621 // Nothing has been sent to the proxy resolver yet, since the proxy
1622 // resolver has not been configured yet.
1623 ASSERT_EQ(0u, resolver.pending_requests().size());
1625 // Successfully initialize the PAC script.
1626 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1627 resolver.pending_set_pac_script_request()->script_data()->url());
1628 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1630 ASSERT_EQ(1u, resolver.pending_requests().size());
1631 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1633 ProxyInfo info2;
1634 TestCompletionCallback callback2;
1635 ProxyService::PacRequest* request2;
1636 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1637 callback2.callback(), &request2, NULL,
1638 BoundNetLog());
1639 EXPECT_EQ(ERR_IO_PENDING, rv);
1640 ASSERT_EQ(2u, resolver.pending_requests().size());
1641 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
1643 ProxyInfo info3;
1644 TestCompletionCallback callback3;
1645 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
1646 callback3.callback(), NULL, NULL, BoundNetLog());
1647 EXPECT_EQ(ERR_IO_PENDING, rv);
1648 ASSERT_EQ(3u, resolver.pending_requests().size());
1649 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[2]->url());
1651 // Cancel the second request
1652 service.CancelPacRequest(request2);
1654 ASSERT_EQ(2u, resolver.pending_requests().size());
1655 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1656 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[1]->url());
1658 // Complete the two un-cancelled requests.
1659 // We complete the last one first, just to mix it up a bit.
1660 resolver.pending_requests()[1]->results()->UseNamedProxy("request3:80");
1661 resolver.pending_requests()[1]->CompleteNow(OK);
1663 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
1664 resolver.pending_requests()[0]->CompleteNow(OK);
1666 // Complete and verify that requests ran as expected.
1667 EXPECT_EQ(OK, callback1.WaitForResult());
1668 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1670 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1671 ASSERT_EQ(1u, resolver.cancelled_requests().size());
1672 EXPECT_EQ(GURL("http://request2"), resolver.cancelled_requests()[0]->url());
1674 EXPECT_EQ(OK, callback3.WaitForResult());
1675 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1678 // Test the initial PAC download for resolver that expects bytes.
1679 TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
1680 MockProxyConfigService* config_service =
1681 new MockProxyConfigService("http://foopy/proxy.pac");
1683 MockAsyncProxyResolverExpectsBytes resolver;
1685 ProxyService service(
1686 config_service,
1687 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1689 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1690 service.SetProxyScriptFetchers(fetcher,
1691 new DoNothingDhcpProxyScriptFetcher());
1693 // Start 3 requests.
1695 ProxyInfo info1;
1696 TestCompletionCallback callback1;
1697 ProxyService::PacRequest* request1;
1698 int rv = service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1699 callback1.callback(), &request1, NULL,
1700 BoundNetLog());
1701 EXPECT_EQ(ERR_IO_PENDING, rv);
1703 // The first request should have triggered download of PAC script.
1704 EXPECT_TRUE(fetcher->has_pending_request());
1705 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1707 ProxyInfo info2;
1708 TestCompletionCallback callback2;
1709 ProxyService::PacRequest* request2;
1710 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1711 callback2.callback(), &request2, NULL,
1712 BoundNetLog());
1713 EXPECT_EQ(ERR_IO_PENDING, rv);
1715 ProxyInfo info3;
1716 TestCompletionCallback callback3;
1717 ProxyService::PacRequest* request3;
1718 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
1719 callback3.callback(), &request3, NULL,
1720 BoundNetLog());
1721 EXPECT_EQ(ERR_IO_PENDING, rv);
1723 // Nothing has been sent to the resolver yet.
1724 EXPECT_TRUE(resolver.pending_requests().empty());
1726 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1727 service.GetLoadState(request1));
1728 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1729 service.GetLoadState(request2));
1730 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1731 service.GetLoadState(request3));
1733 // At this point the ProxyService should be waiting for the
1734 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1735 // PAC script download completion.
1736 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1738 // Now that the PAC script is downloaded, it will have been sent to the proxy
1739 // resolver.
1740 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1741 resolver.pending_set_pac_script_request()->script_data()->utf16());
1742 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1744 ASSERT_EQ(3u, resolver.pending_requests().size());
1745 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1746 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
1747 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[2]->url());
1749 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1));
1750 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2));
1751 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3));
1753 // Complete all the requests (in some order).
1754 // Note that as we complete requests, they shift up in |pending_requests()|.
1756 resolver.pending_requests()[2]->results()->UseNamedProxy("request3:80");
1757 resolver.pending_requests()[2]->CompleteNow(OK);
1759 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
1760 resolver.pending_requests()[0]->CompleteNow(OK);
1762 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
1763 resolver.pending_requests()[0]->CompleteNow(OK);
1765 // Complete and verify that requests ran as expected.
1766 EXPECT_EQ(OK, callback1.WaitForResult());
1767 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1768 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1769 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1770 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
1772 EXPECT_EQ(OK, callback2.WaitForResult());
1773 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1774 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
1775 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
1776 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
1778 EXPECT_EQ(OK, callback3.WaitForResult());
1779 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1780 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
1781 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
1782 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
1785 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1786 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
1787 MockProxyConfigService* config_service =
1788 new MockProxyConfigService("http://foopy/proxy.pac");
1790 MockAsyncProxyResolverExpectsBytes resolver;
1792 ProxyService service(
1793 config_service,
1794 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1796 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1797 service.SetProxyScriptFetchers(fetcher,
1798 new DoNothingDhcpProxyScriptFetcher());
1800 // Start 2 requests.
1802 ProxyInfo info1;
1803 TestCompletionCallback callback1;
1804 int rv =
1805 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1806 callback1.callback(), NULL, NULL, BoundNetLog());
1807 EXPECT_EQ(ERR_IO_PENDING, rv);
1809 // The first request should have triggered download of PAC script.
1810 EXPECT_TRUE(fetcher->has_pending_request());
1811 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1813 ProxyInfo info2;
1814 TestCompletionCallback callback2;
1815 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1816 callback2.callback(), NULL, NULL, BoundNetLog());
1817 EXPECT_EQ(ERR_IO_PENDING, rv);
1819 // At this point the ProxyService should be waiting for the
1820 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1821 // PAC script download completion.
1823 // We now change out the ProxyService's script fetcher. We should restart
1824 // the initialization with the new fetcher.
1826 fetcher = new MockProxyScriptFetcher;
1827 service.SetProxyScriptFetchers(fetcher,
1828 new DoNothingDhcpProxyScriptFetcher());
1830 // Nothing has been sent to the resolver yet.
1831 EXPECT_TRUE(resolver.pending_requests().empty());
1833 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1835 // Now that the PAC script is downloaded, it will have been sent to the proxy
1836 // resolver.
1837 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1838 resolver.pending_set_pac_script_request()->script_data()->utf16());
1839 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1841 ASSERT_EQ(2u, resolver.pending_requests().size());
1842 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1843 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
1846 // Test cancellation of a request, while the PAC script is being fetched.
1847 TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
1848 MockProxyConfigService* config_service =
1849 new MockProxyConfigService("http://foopy/proxy.pac");
1851 MockAsyncProxyResolverExpectsBytes resolver;
1853 ProxyService service(
1854 config_service,
1855 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1857 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1858 service.SetProxyScriptFetchers(fetcher,
1859 new DoNothingDhcpProxyScriptFetcher());
1861 // Start 3 requests.
1862 ProxyInfo info1;
1863 TestCompletionCallback callback1;
1864 ProxyService::PacRequest* request1;
1865 BoundTestNetLog log1;
1866 int rv =
1867 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1868 callback1.callback(), &request1, NULL, log1.bound());
1869 EXPECT_EQ(ERR_IO_PENDING, rv);
1871 // The first request should have triggered download of PAC script.
1872 EXPECT_TRUE(fetcher->has_pending_request());
1873 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1875 ProxyInfo info2;
1876 TestCompletionCallback callback2;
1877 ProxyService::PacRequest* request2;
1878 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1879 callback2.callback(), &request2, NULL,
1880 BoundNetLog());
1881 EXPECT_EQ(ERR_IO_PENDING, rv);
1883 ProxyInfo info3;
1884 TestCompletionCallback callback3;
1885 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
1886 callback3.callback(), NULL, NULL, BoundNetLog());
1887 EXPECT_EQ(ERR_IO_PENDING, rv);
1889 // Nothing has been sent to the resolver yet.
1890 EXPECT_TRUE(resolver.pending_requests().empty());
1892 // Cancel the first 2 requests.
1893 service.CancelPacRequest(request1);
1894 service.CancelPacRequest(request2);
1896 // At this point the ProxyService should be waiting for the
1897 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1898 // PAC script download completion.
1899 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1901 // Now that the PAC script is downloaded, it will have been sent to the
1902 // proxy resolver.
1903 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1904 resolver.pending_set_pac_script_request()->script_data()->utf16());
1905 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1907 ASSERT_EQ(1u, resolver.pending_requests().size());
1908 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[0]->url());
1910 // Complete all the requests.
1911 resolver.pending_requests()[0]->results()->UseNamedProxy("request3:80");
1912 resolver.pending_requests()[0]->CompleteNow(OK);
1914 EXPECT_EQ(OK, callback3.WaitForResult());
1915 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1917 EXPECT_TRUE(resolver.cancelled_requests().empty());
1919 EXPECT_FALSE(callback1.have_result()); // Cancelled.
1920 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1922 TestNetLog::CapturedEntryList entries1;
1923 log1.GetEntries(&entries1);
1925 // Check the NetLog for request 1 (which was cancelled) got filled properly.
1926 EXPECT_EQ(4u, entries1.size());
1927 EXPECT_TRUE(LogContainsBeginEvent(
1928 entries1, 0, NetLog::TYPE_PROXY_SERVICE));
1929 EXPECT_TRUE(LogContainsBeginEvent(
1930 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
1931 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1932 // the cancellation occured.
1933 EXPECT_TRUE(LogContainsEvent(
1934 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
1935 EXPECT_TRUE(LogContainsEndEvent(
1936 entries1, 3, NetLog::TYPE_PROXY_SERVICE));
1939 // Test that if auto-detect fails, we fall-back to the custom pac.
1940 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
1941 ProxyConfig config;
1942 config.set_auto_detect(true);
1943 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1944 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1946 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1947 MockAsyncProxyResolverExpectsBytes resolver;
1948 ProxyService service(
1949 config_service,
1950 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
1952 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1953 service.SetProxyScriptFetchers(fetcher,
1954 new DoNothingDhcpProxyScriptFetcher());
1956 // Start 2 requests.
1958 ProxyInfo info1;
1959 TestCompletionCallback callback1;
1960 int rv =
1961 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1962 callback1.callback(), NULL, NULL, BoundNetLog());
1963 EXPECT_EQ(ERR_IO_PENDING, rv);
1965 ProxyInfo info2;
1966 TestCompletionCallback callback2;
1967 ProxyService::PacRequest* request2;
1968 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1969 callback2.callback(), &request2, NULL,
1970 BoundNetLog());
1971 EXPECT_EQ(ERR_IO_PENDING, rv);
1973 // Check that nothing has been sent to the proxy resolver yet.
1974 ASSERT_EQ(0u, resolver.pending_requests().size());
1976 // It should be trying to auto-detect first -- FAIL the autodetect during
1977 // the script download.
1978 EXPECT_TRUE(fetcher->has_pending_request());
1979 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1980 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
1982 // Next it should be trying the custom PAC url.
1983 EXPECT_TRUE(fetcher->has_pending_request());
1984 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1985 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1987 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1988 resolver.pending_set_pac_script_request()->script_data()->utf16());
1989 resolver.pending_set_pac_script_request()->CompleteNow(OK);
1991 // Now finally, the pending requests should have been sent to the resolver
1992 // (which was initialized with custom PAC script).
1994 ASSERT_EQ(2u, resolver.pending_requests().size());
1995 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1996 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
1998 // Complete the pending requests.
1999 resolver.pending_requests()[1]->results()->UseNamedProxy("request2:80");
2000 resolver.pending_requests()[1]->CompleteNow(OK);
2001 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2002 resolver.pending_requests()[0]->CompleteNow(OK);
2004 // Verify that requests ran as expected.
2005 EXPECT_EQ(OK, callback1.WaitForResult());
2006 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2007 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
2008 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
2009 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
2011 EXPECT_EQ(OK, callback2.WaitForResult());
2012 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2013 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
2014 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
2015 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
2018 // This is the same test as FallbackFromAutodetectToCustomPac, except
2019 // the auto-detect script fails parsing rather than downloading.
2020 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
2021 ProxyConfig config;
2022 config.set_auto_detect(true);
2023 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2024 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2026 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2027 MockAsyncProxyResolverExpectsBytes resolver;
2028 ProxyService service(
2029 config_service,
2030 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2032 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2033 service.SetProxyScriptFetchers(fetcher,
2034 new DoNothingDhcpProxyScriptFetcher());
2036 // Start 2 requests.
2038 ProxyInfo info1;
2039 TestCompletionCallback callback1;
2040 int rv =
2041 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2042 callback1.callback(), NULL, NULL, BoundNetLog());
2043 EXPECT_EQ(ERR_IO_PENDING, rv);
2045 ProxyInfo info2;
2046 TestCompletionCallback callback2;
2047 ProxyService::PacRequest* request2;
2048 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2049 callback2.callback(), &request2, NULL,
2050 BoundNetLog());
2051 EXPECT_EQ(ERR_IO_PENDING, rv);
2053 // Check that nothing has been sent to the proxy resolver yet.
2054 ASSERT_EQ(0u, resolver.pending_requests().size());
2056 // It should be trying to auto-detect first -- succeed the download.
2057 EXPECT_TRUE(fetcher->has_pending_request());
2058 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2059 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
2061 // The script contents passed failed basic verification step (since didn't
2062 // contain token FindProxyForURL), so it was never passed to the resolver.
2064 // Next it should be trying the custom PAC url.
2065 EXPECT_TRUE(fetcher->has_pending_request());
2066 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2067 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2069 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2070 resolver.pending_set_pac_script_request()->script_data()->utf16());
2071 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2073 // Now finally, the pending requests should have been sent to the resolver
2074 // (which was initialized with custom PAC script).
2076 ASSERT_EQ(2u, resolver.pending_requests().size());
2077 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2078 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
2080 // Complete the pending requests.
2081 resolver.pending_requests()[1]->results()->UseNamedProxy("request2:80");
2082 resolver.pending_requests()[1]->CompleteNow(OK);
2083 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2084 resolver.pending_requests()[0]->CompleteNow(OK);
2086 // Verify that requests ran as expected.
2087 EXPECT_EQ(OK, callback1.WaitForResult());
2088 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2090 EXPECT_EQ(OK, callback2.WaitForResult());
2091 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2094 // Test that if all of auto-detect, a custom PAC script, and manual settings
2095 // are given, then we will try them in that order.
2096 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
2097 ProxyConfig config;
2098 config.set_auto_detect(true);
2099 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2100 config.proxy_rules().ParseFromString("http=foopy:80");
2102 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2103 MockAsyncProxyResolverExpectsBytes resolver;
2104 ProxyService service(
2105 config_service,
2106 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2108 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2109 service.SetProxyScriptFetchers(fetcher,
2110 new DoNothingDhcpProxyScriptFetcher());
2112 // Start 2 requests.
2114 ProxyInfo info1;
2115 TestCompletionCallback callback1;
2116 int rv =
2117 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2118 callback1.callback(), NULL, NULL, BoundNetLog());
2119 EXPECT_EQ(ERR_IO_PENDING, rv);
2121 ProxyInfo info2;
2122 TestCompletionCallback callback2;
2123 ProxyService::PacRequest* request2;
2124 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2125 callback2.callback(), &request2, NULL,
2126 BoundNetLog());
2127 EXPECT_EQ(ERR_IO_PENDING, rv);
2129 // Check that nothing has been sent to the proxy resolver yet.
2130 ASSERT_EQ(0u, resolver.pending_requests().size());
2132 // It should be trying to auto-detect first -- fail the download.
2133 EXPECT_TRUE(fetcher->has_pending_request());
2134 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2135 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2137 // Next it should be trying the custom PAC url -- fail the download.
2138 EXPECT_TRUE(fetcher->has_pending_request());
2139 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2140 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2142 // Since we never managed to initialize a resolver, nothing should have been
2143 // sent to it.
2144 ASSERT_EQ(0u, resolver.pending_requests().size());
2146 // Verify that requests ran as expected -- they should have fallen back to
2147 // the manual proxy configuration for HTTP urls.
2148 EXPECT_EQ(OK, callback1.WaitForResult());
2149 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
2151 EXPECT_EQ(OK, callback2.WaitForResult());
2152 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
2155 // Test that the bypass rules are NOT applied when using autodetect.
2156 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
2157 ProxyConfig config;
2158 config.set_auto_detect(true);
2159 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2160 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
2161 config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
2163 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2164 MockAsyncProxyResolverExpectsBytes resolver;
2165 ProxyService service(
2166 config_service,
2167 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2169 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2170 service.SetProxyScriptFetchers(fetcher,
2171 new DoNothingDhcpProxyScriptFetcher());
2173 // Start 1 requests.
2175 ProxyInfo info1;
2176 TestCompletionCallback callback1;
2177 int rv =
2178 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2179 callback1.callback(), NULL, NULL, BoundNetLog());
2180 EXPECT_EQ(ERR_IO_PENDING, rv);
2182 // Check that nothing has been sent to the proxy resolver yet.
2183 ASSERT_EQ(0u, resolver.pending_requests().size());
2185 // It should be trying to auto-detect first -- succeed the download.
2186 EXPECT_TRUE(fetcher->has_pending_request());
2187 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2188 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2190 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2191 resolver.pending_set_pac_script_request()->script_data()->utf16());
2192 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2194 ASSERT_EQ(1u, resolver.pending_requests().size());
2195 EXPECT_EQ(GURL("http://www.google.com"),
2196 resolver.pending_requests()[0]->url());
2198 // Complete the pending request.
2199 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2200 resolver.pending_requests()[0]->CompleteNow(OK);
2202 // Verify that request ran as expected.
2203 EXPECT_EQ(OK, callback1.WaitForResult());
2204 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2206 // Start another request, it should pickup the bypass item.
2207 ProxyInfo info2;
2208 TestCompletionCallback callback2;
2209 rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
2210 callback2.callback(), NULL, NULL, BoundNetLog());
2211 EXPECT_EQ(ERR_IO_PENDING, rv);
2213 ASSERT_EQ(1u, resolver.pending_requests().size());
2214 EXPECT_EQ(GURL("http://www.google.com"),
2215 resolver.pending_requests()[0]->url());
2217 // Complete the pending request.
2218 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2219 resolver.pending_requests()[0]->CompleteNow(OK);
2221 EXPECT_EQ(OK, callback2.WaitForResult());
2222 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2225 // Delete the ProxyService while InitProxyResolver has an outstanding
2226 // request to the script fetcher. When run under valgrind, should not
2227 // have any memory errors (used to be that the ProxyScriptFetcher was
2228 // being deleted prior to the InitProxyResolver).
2229 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
2230 ProxyConfig config =
2231 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
2233 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2234 MockAsyncProxyResolverExpectsBytes resolver;
2235 ProxyService service(
2236 config_service,
2237 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2239 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2240 service.SetProxyScriptFetchers(fetcher,
2241 new DoNothingDhcpProxyScriptFetcher());
2243 // Start 1 request.
2245 ProxyInfo info1;
2246 TestCompletionCallback callback1;
2247 int rv =
2248 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2249 callback1.callback(), NULL, NULL, BoundNetLog());
2250 EXPECT_EQ(ERR_IO_PENDING, rv);
2252 // Check that nothing has been sent to the proxy resolver yet.
2253 ASSERT_EQ(0u, resolver.pending_requests().size());
2255 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
2256 // and be waiting on that to complete.
2257 EXPECT_TRUE(fetcher->has_pending_request());
2258 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2261 // Delete the ProxyService while InitProxyResolver has an outstanding
2262 // request to the proxy resolver. When run under valgrind, should not
2263 // have any memory errors (used to be that the ProxyResolver was
2264 // being deleted prior to the InitProxyResolver).
2265 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
2266 MockProxyConfigService* config_service =
2267 new MockProxyConfigService("http://foopy/proxy.pac");
2269 MockAsyncProxyResolver resolver;
2271 ProxyService service(
2272 config_service,
2273 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2275 GURL url("http://www.google.com/");
2277 ProxyInfo info;
2278 TestCompletionCallback callback;
2279 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
2280 NULL, NULL, BoundNetLog());
2281 EXPECT_EQ(ERR_IO_PENDING, rv);
2283 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2284 resolver.pending_set_pac_script_request()->script_data()->url());
2287 TEST_F(ProxyServiceTest, ResetProxyConfigService) {
2288 ProxyConfig config1;
2289 config1.proxy_rules().ParseFromString("foopy1:8080");
2290 config1.set_auto_detect(false);
2291 ProxyService service(new MockProxyConfigService(config1), nullptr, NULL);
2293 ProxyInfo info;
2294 TestCompletionCallback callback1;
2295 int rv =
2296 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info,
2297 callback1.callback(), NULL, NULL, BoundNetLog());
2298 EXPECT_EQ(OK, rv);
2299 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
2301 ProxyConfig config2;
2302 config2.proxy_rules().ParseFromString("foopy2:8080");
2303 config2.set_auto_detect(false);
2304 service.ResetConfigService(new MockProxyConfigService(config2));
2305 TestCompletionCallback callback2;
2306 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info,
2307 callback2.callback(), NULL, NULL, BoundNetLog());
2308 EXPECT_EQ(OK, rv);
2309 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
2312 // Test that when going from a configuration that required PAC to one
2313 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2314 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
2315 ProxyConfig config = ProxyConfig::CreateAutoDetect();
2317 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2318 MockAsyncProxyResolver resolver;
2319 ProxyService service(
2320 config_service,
2321 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2323 // Start 1 request.
2325 ProxyInfo info1;
2326 TestCompletionCallback callback1;
2327 int rv =
2328 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2329 callback1.callback(), NULL, NULL, BoundNetLog());
2330 EXPECT_EQ(ERR_IO_PENDING, rv);
2332 // Check that nothing has been sent to the proxy resolver yet.
2333 ASSERT_EQ(0u, resolver.pending_requests().size());
2335 // Successfully set the autodetect script.
2336 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT,
2337 resolver.pending_set_pac_script_request()->script_data()->type());
2338 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2340 // Complete the pending request.
2341 ASSERT_EQ(1u, resolver.pending_requests().size());
2342 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2343 resolver.pending_requests()[0]->CompleteNow(OK);
2345 // Verify that request ran as expected.
2346 EXPECT_EQ(OK, callback1.WaitForResult());
2347 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2349 // Force the ProxyService to pull down a new proxy configuration.
2350 // (Even though the configuration isn't old/bad).
2352 // This new configuration no longer has auto_detect set, so
2353 // requests should complete synchronously now as direct-connect.
2354 config_service->SetConfig(ProxyConfig::CreateDirect());
2356 // Start another request -- the effective configuration has changed.
2357 ProxyInfo info2;
2358 TestCompletionCallback callback2;
2359 rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
2360 callback2.callback(), NULL, NULL, BoundNetLog());
2361 EXPECT_EQ(OK, rv);
2363 EXPECT_TRUE(info2.is_direct());
2366 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
2367 MockProxyConfigService* config_service =
2368 new MockProxyConfigService("http://foopy/proxy.pac");
2370 MockAsyncProxyResolverExpectsBytes resolver;
2372 TestNetLog log;
2374 ProxyService service(
2375 config_service,
2376 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), &log);
2378 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2379 service.SetProxyScriptFetchers(fetcher,
2380 new DoNothingDhcpProxyScriptFetcher());
2382 // Disable the "wait after IP address changes" hack, so this unit-test can
2383 // complete quickly.
2384 service.set_stall_proxy_auto_config_delay(base::TimeDelta());
2386 // Start 1 request.
2388 ProxyInfo info1;
2389 TestCompletionCallback callback1;
2390 int rv =
2391 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2392 callback1.callback(), NULL, NULL, BoundNetLog());
2393 EXPECT_EQ(ERR_IO_PENDING, rv);
2395 // The first request should have triggered initial download of PAC script.
2396 EXPECT_TRUE(fetcher->has_pending_request());
2397 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2399 // Nothing has been sent to the resolver yet.
2400 EXPECT_TRUE(resolver.pending_requests().empty());
2402 // At this point the ProxyService should be waiting for the
2403 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2404 // PAC script download completion.
2405 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2407 // Now that the PAC script is downloaded, the request will have been sent to
2408 // the proxy resolver.
2409 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2410 resolver.pending_set_pac_script_request()->script_data()->utf16());
2411 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2413 ASSERT_EQ(1u, resolver.pending_requests().size());
2414 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2416 // Complete the pending request.
2417 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2418 resolver.pending_requests()[0]->CompleteNow(OK);
2420 // Wait for completion callback, and verify that the request ran as expected.
2421 EXPECT_EQ(OK, callback1.WaitForResult());
2422 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2424 // Now simluate a change in the network. The ProxyConfigService is still
2425 // going to return the same PAC URL as before, but this URL needs to be
2426 // refetched on the new network.
2427 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2428 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2430 // Start a second request.
2431 ProxyInfo info2;
2432 TestCompletionCallback callback2;
2433 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2434 callback2.callback(), NULL, NULL, BoundNetLog());
2435 EXPECT_EQ(ERR_IO_PENDING, rv);
2437 // This second request should have triggered the re-download of the PAC
2438 // script (since we marked the network as having changed).
2439 EXPECT_TRUE(fetcher->has_pending_request());
2440 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2442 // Nothing has been sent to the resolver yet.
2443 EXPECT_TRUE(resolver.pending_requests().empty());
2445 // Simulate the PAC script fetch as having completed (this time with
2446 // different data).
2447 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2449 // Now that the PAC script is downloaded, the second request will have been
2450 // sent to the proxy resolver.
2451 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2452 resolver.pending_set_pac_script_request()->script_data()->utf16());
2453 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2455 ASSERT_EQ(1u, resolver.pending_requests().size());
2456 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2458 // Complete the pending second request.
2459 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2460 resolver.pending_requests()[0]->CompleteNow(OK);
2462 // Wait for completion callback, and verify that the request ran as expected.
2463 EXPECT_EQ(OK, callback2.WaitForResult());
2464 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2466 // Check that the expected events were output to the log stream. In particular
2467 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2468 // setup), and NOT a second time when the IP address changed.
2469 TestNetLog::CapturedEntryList entries;
2470 log.GetEntries(&entries);
2472 EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
2473 NetLog::TYPE_PROXY_CONFIG_CHANGED));
2474 ASSERT_EQ(9u, entries.size());
2475 for (size_t i = 1; i < entries.size(); ++i)
2476 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
2479 // This test verifies that the PAC script specified by the settings is
2480 // periodically polled for changes. Specifically, if the initial fetch fails due
2481 // to a network error, we will eventually re-configure the service to use the
2482 // script once it becomes available.
2483 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
2484 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2485 // runs quickly.
2486 ImmediatePollPolicy poll_policy;
2487 ProxyService::set_pac_script_poll_policy(&poll_policy);
2489 MockProxyConfigService* config_service =
2490 new MockProxyConfigService("http://foopy/proxy.pac");
2492 MockAsyncProxyResolverExpectsBytes resolver;
2494 ProxyService service(
2495 config_service,
2496 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2498 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2499 service.SetProxyScriptFetchers(fetcher,
2500 new DoNothingDhcpProxyScriptFetcher());
2502 // Start 1 request.
2504 ProxyInfo info1;
2505 TestCompletionCallback callback1;
2506 int rv =
2507 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2508 callback1.callback(), NULL, NULL, BoundNetLog());
2509 EXPECT_EQ(ERR_IO_PENDING, rv);
2511 // The first request should have triggered initial download of PAC script.
2512 EXPECT_TRUE(fetcher->has_pending_request());
2513 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2515 // Nothing has been sent to the resolver yet.
2516 EXPECT_TRUE(resolver.pending_requests().empty());
2518 // At this point the ProxyService should be waiting for the
2519 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2520 // PAC script download completion.
2522 // We simulate a failed download attempt, the proxy service should now
2523 // fall-back to DIRECT connections.
2524 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2526 ASSERT_TRUE(resolver.pending_requests().empty());
2528 // Wait for completion callback, and verify it used DIRECT.
2529 EXPECT_EQ(OK, callback1.WaitForResult());
2530 EXPECT_TRUE(info1.is_direct());
2532 // At this point we have initialized the proxy service using a PAC script,
2533 // however it failed and fell-back to DIRECT.
2535 // A background task to periodically re-check the PAC script for validity will
2536 // have been started. We will now wait for the next download attempt to start.
2538 // Note that we shouldn't have to wait long here, since our test enables a
2539 // special unit-test mode.
2540 fetcher->WaitUntilFetch();
2542 ASSERT_TRUE(resolver.pending_requests().empty());
2544 // Make sure that our background checker is trying to download the expected
2545 // PAC script (same one as before). This time we will simulate a successful
2546 // download of the script.
2547 EXPECT_TRUE(fetcher->has_pending_request());
2548 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2549 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2551 base::MessageLoop::current()->RunUntilIdle();
2553 // Now that the PAC script is downloaded, it should be used to initialize the
2554 // ProxyResolver. Simulate a successful parse.
2555 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2556 resolver.pending_set_pac_script_request()->script_data()->utf16());
2557 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2559 // At this point the ProxyService should have re-configured itself to use the
2560 // PAC script (thereby recovering from the initial fetch failure). We will
2561 // verify that the next Resolve request uses the resolver rather than
2562 // DIRECT.
2564 // Start a second request.
2565 ProxyInfo info2;
2566 TestCompletionCallback callback2;
2567 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2568 callback2.callback(), NULL, NULL, BoundNetLog());
2569 EXPECT_EQ(ERR_IO_PENDING, rv);
2571 // Check that it was sent to the resolver.
2572 ASSERT_EQ(1u, resolver.pending_requests().size());
2573 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2575 // Complete the pending second request.
2576 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2577 resolver.pending_requests()[0]->CompleteNow(OK);
2579 // Wait for completion callback, and verify that the request ran as expected.
2580 EXPECT_EQ(OK, callback2.WaitForResult());
2581 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2584 // This test verifies that the PAC script specified by the settings is
2585 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2586 // however at a later time its *contents* change, we will eventually
2587 // re-configure the service to use the new script.
2588 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
2589 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2590 // runs quickly.
2591 ImmediatePollPolicy poll_policy;
2592 ProxyService::set_pac_script_poll_policy(&poll_policy);
2594 MockProxyConfigService* config_service =
2595 new MockProxyConfigService("http://foopy/proxy.pac");
2597 MockAsyncProxyResolverExpectsBytes resolver;
2599 ProxyService service(
2600 config_service,
2601 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2603 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2604 service.SetProxyScriptFetchers(fetcher,
2605 new DoNothingDhcpProxyScriptFetcher());
2607 // Start 1 request.
2609 ProxyInfo info1;
2610 TestCompletionCallback callback1;
2611 int rv =
2612 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2613 callback1.callback(), NULL, NULL, BoundNetLog());
2614 EXPECT_EQ(ERR_IO_PENDING, rv);
2616 // The first request should have triggered initial download of PAC script.
2617 EXPECT_TRUE(fetcher->has_pending_request());
2618 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2620 // Nothing has been sent to the resolver yet.
2621 EXPECT_TRUE(resolver.pending_requests().empty());
2623 // At this point the ProxyService should be waiting for the
2624 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2625 // PAC script download completion.
2626 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2628 // Now that the PAC script is downloaded, the request will have been sent to
2629 // the proxy resolver.
2630 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2631 resolver.pending_set_pac_script_request()->script_data()->utf16());
2632 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2634 ASSERT_EQ(1u, resolver.pending_requests().size());
2635 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2637 // Complete the pending request.
2638 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2639 resolver.pending_requests()[0]->CompleteNow(OK);
2641 // Wait for completion callback, and verify that the request ran as expected.
2642 EXPECT_EQ(OK, callback1.WaitForResult());
2643 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2645 // At this point we have initialized the proxy service using a PAC script.
2647 // A background task to periodically re-check the PAC script for validity will
2648 // have been started. We will now wait for the next download attempt to start.
2650 // Note that we shouldn't have to wait long here, since our test enables a
2651 // special unit-test mode.
2652 fetcher->WaitUntilFetch();
2654 ASSERT_TRUE(resolver.pending_requests().empty());
2656 // Make sure that our background checker is trying to download the expected
2657 // PAC script (same one as before). This time we will simulate a successful
2658 // download of a DIFFERENT script.
2659 EXPECT_TRUE(fetcher->has_pending_request());
2660 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2661 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2663 base::MessageLoop::current()->RunUntilIdle();
2665 // Now that the PAC script is downloaded, it should be used to initialize the
2666 // ProxyResolver. Simulate a successful parse.
2667 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2668 resolver.pending_set_pac_script_request()->script_data()->utf16());
2669 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2671 // At this point the ProxyService should have re-configured itself to use the
2672 // new PAC script.
2674 // Start a second request.
2675 ProxyInfo info2;
2676 TestCompletionCallback callback2;
2677 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2678 callback2.callback(), NULL, NULL, BoundNetLog());
2679 EXPECT_EQ(ERR_IO_PENDING, rv);
2681 // Check that it was sent to the resolver.
2682 ASSERT_EQ(1u, resolver.pending_requests().size());
2683 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2685 // Complete the pending second request.
2686 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2687 resolver.pending_requests()[0]->CompleteNow(OK);
2689 // Wait for completion callback, and verify that the request ran as expected.
2690 EXPECT_EQ(OK, callback2.WaitForResult());
2691 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2694 // This test verifies that the PAC script specified by the settings is
2695 // periodically polled for changes. Specifically, if the initial fetch succeeds
2696 // and so does the next poll, however the contents of the downloaded script
2697 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2698 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
2699 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2700 // runs quickly.
2701 ImmediatePollPolicy poll_policy;
2702 ProxyService::set_pac_script_poll_policy(&poll_policy);
2704 MockProxyConfigService* config_service =
2705 new MockProxyConfigService("http://foopy/proxy.pac");
2707 MockAsyncProxyResolverExpectsBytes resolver;
2709 ProxyService service(
2710 config_service,
2711 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2713 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2714 service.SetProxyScriptFetchers(fetcher,
2715 new DoNothingDhcpProxyScriptFetcher());
2717 // Start 1 request.
2719 ProxyInfo info1;
2720 TestCompletionCallback callback1;
2721 int rv =
2722 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2723 callback1.callback(), NULL, NULL, BoundNetLog());
2724 EXPECT_EQ(ERR_IO_PENDING, rv);
2726 // The first request should have triggered initial download of PAC script.
2727 EXPECT_TRUE(fetcher->has_pending_request());
2728 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2730 // Nothing has been sent to the resolver yet.
2731 EXPECT_TRUE(resolver.pending_requests().empty());
2733 // At this point the ProxyService should be waiting for the
2734 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2735 // PAC script download completion.
2736 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2738 // Now that the PAC script is downloaded, the request will have been sent to
2739 // the proxy resolver.
2740 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2741 resolver.pending_set_pac_script_request()->script_data()->utf16());
2742 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2744 ASSERT_EQ(1u, resolver.pending_requests().size());
2745 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2747 // Complete the pending request.
2748 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2749 resolver.pending_requests()[0]->CompleteNow(OK);
2751 // Wait for completion callback, and verify that the request ran as expected.
2752 EXPECT_EQ(OK, callback1.WaitForResult());
2753 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2755 // At this point we have initialized the proxy service using a PAC script.
2757 // A background task to periodically re-check the PAC script for validity will
2758 // have been started. We will now wait for the next download attempt to start.
2760 // Note that we shouldn't have to wait long here, since our test enables a
2761 // special unit-test mode.
2762 fetcher->WaitUntilFetch();
2764 ASSERT_TRUE(resolver.pending_requests().empty());
2766 // Make sure that our background checker is trying to download the expected
2767 // PAC script (same one as before). We will simulate the same response as
2768 // last time (i.e. the script is unchanged).
2769 EXPECT_TRUE(fetcher->has_pending_request());
2770 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2771 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2773 base::MessageLoop::current()->RunUntilIdle();
2775 ASSERT_FALSE(resolver.has_pending_set_pac_script_request());
2777 // At this point the ProxyService is still running the same PAC script as
2778 // before.
2780 // Start a second request.
2781 ProxyInfo info2;
2782 TestCompletionCallback callback2;
2783 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2784 callback2.callback(), NULL, NULL, BoundNetLog());
2785 EXPECT_EQ(ERR_IO_PENDING, rv);
2787 // Check that it was sent to the resolver.
2788 ASSERT_EQ(1u, resolver.pending_requests().size());
2789 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2791 // Complete the pending second request.
2792 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2793 resolver.pending_requests()[0]->CompleteNow(OK);
2795 // Wait for completion callback, and verify that the request ran as expected.
2796 EXPECT_EQ(OK, callback2.WaitForResult());
2797 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2800 // This test verifies that the PAC script specified by the settings is
2801 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2802 // however at a later time it starts to fail, we should re-configure the
2803 // ProxyService to stop using that PAC script.
2804 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
2805 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2806 // runs quickly.
2807 ImmediatePollPolicy poll_policy;
2808 ProxyService::set_pac_script_poll_policy(&poll_policy);
2810 MockProxyConfigService* config_service =
2811 new MockProxyConfigService("http://foopy/proxy.pac");
2813 MockAsyncProxyResolverExpectsBytes resolver;
2815 ProxyService service(
2816 config_service,
2817 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2819 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2820 service.SetProxyScriptFetchers(fetcher,
2821 new DoNothingDhcpProxyScriptFetcher());
2823 // Start 1 request.
2825 ProxyInfo info1;
2826 TestCompletionCallback callback1;
2827 int rv =
2828 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2829 callback1.callback(), NULL, NULL, BoundNetLog());
2830 EXPECT_EQ(ERR_IO_PENDING, rv);
2832 // The first request should have triggered initial download of PAC script.
2833 EXPECT_TRUE(fetcher->has_pending_request());
2834 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2836 // Nothing has been sent to the resolver yet.
2837 EXPECT_TRUE(resolver.pending_requests().empty());
2839 // At this point the ProxyService should be waiting for the
2840 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2841 // PAC script download completion.
2842 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2844 // Now that the PAC script is downloaded, the request will have been sent to
2845 // the proxy resolver.
2846 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2847 resolver.pending_set_pac_script_request()->script_data()->utf16());
2848 resolver.pending_set_pac_script_request()->CompleteNow(OK);
2850 ASSERT_EQ(1u, resolver.pending_requests().size());
2851 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2853 // Complete the pending request.
2854 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2855 resolver.pending_requests()[0]->CompleteNow(OK);
2857 // Wait for completion callback, and verify that the request ran as expected.
2858 EXPECT_EQ(OK, callback1.WaitForResult());
2859 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2861 // At this point we have initialized the proxy service using a PAC script.
2863 // A background task to periodically re-check the PAC script for validity will
2864 // have been started. We will now wait for the next download attempt to start.
2866 // Note that we shouldn't have to wait long here, since our test enables a
2867 // special unit-test mode.
2868 fetcher->WaitUntilFetch();
2870 ASSERT_TRUE(resolver.pending_requests().empty());
2872 // Make sure that our background checker is trying to download the expected
2873 // PAC script (same one as before). This time we will simulate a failure
2874 // to download the script.
2875 EXPECT_TRUE(fetcher->has_pending_request());
2876 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2877 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2879 base::MessageLoop::current()->RunUntilIdle();
2881 // At this point the ProxyService should have re-configured itself to use
2882 // DIRECT connections rather than the given proxy resolver.
2884 // Start a second request.
2885 ProxyInfo info2;
2886 TestCompletionCallback callback2;
2887 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2888 callback2.callback(), NULL, NULL, BoundNetLog());
2889 EXPECT_EQ(OK, rv);
2890 EXPECT_TRUE(info2.is_direct());
2893 // Tests that the code which decides at what times to poll the PAC
2894 // script follows the expected policy.
2895 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) {
2896 // Retrieve the internal polling policy implementation used by ProxyService.
2897 scoped_ptr<ProxyService::PacPollPolicy> policy =
2898 ProxyService::CreateDefaultPacPollPolicy();
2900 int error;
2901 ProxyService::PacPollPolicy::Mode mode;
2902 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1);
2903 base::TimeDelta delay = initial_delay;
2905 // --------------------------------------------------
2906 // Test the poll sequence in response to a failure.
2907 // --------------------------------------------------
2908 error = ERR_NAME_NOT_RESOLVED;
2910 // Poll #0
2911 mode = policy->GetNextDelay(error, initial_delay, &delay);
2912 EXPECT_EQ(8, delay.InSeconds());
2913 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
2915 // Poll #1
2916 mode = policy->GetNextDelay(error, delay, &delay);
2917 EXPECT_EQ(32, delay.InSeconds());
2918 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2920 // Poll #2
2921 mode = policy->GetNextDelay(error, delay, &delay);
2922 EXPECT_EQ(120, delay.InSeconds());
2923 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2925 // Poll #3
2926 mode = policy->GetNextDelay(error, delay, &delay);
2927 EXPECT_EQ(14400, delay.InSeconds());
2928 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2930 // Poll #4
2931 mode = policy->GetNextDelay(error, delay, &delay);
2932 EXPECT_EQ(14400, delay.InSeconds());
2933 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2935 // --------------------------------------------------
2936 // Test the poll sequence in response to a success.
2937 // --------------------------------------------------
2938 error = OK;
2940 // Poll #0
2941 mode = policy->GetNextDelay(error, initial_delay, &delay);
2942 EXPECT_EQ(43200, delay.InSeconds());
2943 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2945 // Poll #1
2946 mode = policy->GetNextDelay(error, delay, &delay);
2947 EXPECT_EQ(43200, delay.InSeconds());
2948 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2950 // Poll #2
2951 mode = policy->GetNextDelay(error, delay, &delay);
2952 EXPECT_EQ(43200, delay.InSeconds());
2953 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2956 // This tests the polling of the PAC script. Specifically, it tests that
2957 // polling occurs in response to user activity.
2958 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
2959 ImmediateAfterActivityPollPolicy poll_policy;
2960 ProxyService::set_pac_script_poll_policy(&poll_policy);
2962 MockProxyConfigService* config_service =
2963 new MockProxyConfigService("http://foopy/proxy.pac");
2965 MockAsyncProxyResolverExpectsBytes resolver;
2967 ProxyService service(
2968 config_service,
2969 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
2971 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2972 service.SetProxyScriptFetchers(fetcher,
2973 new DoNothingDhcpProxyScriptFetcher());
2975 // Start 1 request.
2977 ProxyInfo info1;
2978 TestCompletionCallback callback1;
2979 int rv =
2980 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2981 callback1.callback(), NULL, NULL, BoundNetLog());
2982 EXPECT_EQ(ERR_IO_PENDING, rv);
2984 // The first request should have triggered initial download of PAC script.
2985 EXPECT_TRUE(fetcher->has_pending_request());
2986 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2988 // Nothing has been sent to the resolver yet.
2989 EXPECT_TRUE(resolver.pending_requests().empty());
2991 // At this point the ProxyService should be waiting for the
2992 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2993 // PAC script download completion.
2994 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2996 // Now that the PAC script is downloaded, the request will have been sent to
2997 // the proxy resolver.
2998 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2999 resolver.pending_set_pac_script_request()->script_data()->utf16());
3000 resolver.pending_set_pac_script_request()->CompleteNow(OK);
3002 ASSERT_EQ(1u, resolver.pending_requests().size());
3003 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
3005 // Complete the pending request.
3006 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
3007 resolver.pending_requests()[0]->CompleteNow(OK);
3009 // Wait for completion callback, and verify that the request ran as expected.
3010 EXPECT_EQ(OK, callback1.WaitForResult());
3011 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
3013 // At this point we have initialized the proxy service using a PAC script.
3014 // Our PAC poller is set to update ONLY in response to network activity,
3015 // (i.e. another call to ResolveProxy()).
3017 ASSERT_FALSE(fetcher->has_pending_request());
3018 ASSERT_TRUE(resolver.pending_requests().empty());
3020 // Start a second request.
3021 ProxyInfo info2;
3022 TestCompletionCallback callback2;
3023 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
3024 callback2.callback(), NULL, NULL, BoundNetLog());
3025 EXPECT_EQ(ERR_IO_PENDING, rv);
3027 // This request should have sent work to the resolver; complete it.
3028 ASSERT_EQ(1u, resolver.pending_requests().size());
3029 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
3030 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
3031 resolver.pending_requests()[0]->CompleteNow(OK);
3033 EXPECT_EQ(OK, callback2.WaitForResult());
3034 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
3036 // In response to getting that resolve request, the poller should have
3037 // started the next poll, and made it as far as to request the download.
3039 EXPECT_TRUE(fetcher->has_pending_request());
3040 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3042 // This time we will fail the download, to simulate a PAC script change.
3043 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
3045 // Drain the message loop, so ProxyService is notified of the change
3046 // and has a chance to re-configure itself.
3047 base::MessageLoop::current()->RunUntilIdle();
3049 // Start a third request -- this time we expect to get a direct connection
3050 // since the PAC script poller experienced a failure.
3051 ProxyInfo info3;
3052 TestCompletionCallback callback3;
3053 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
3054 callback3.callback(), NULL, NULL, BoundNetLog());
3055 EXPECT_EQ(OK, rv);
3056 EXPECT_TRUE(info3.is_direct());
3059 // Test that the synchronous resolution fails when a PAC script is active.
3060 TEST_F(ProxyServiceTest, SynchronousWithPAC) {
3061 MockProxyConfigService* config_service =
3062 new MockProxyConfigService("http://foopy/proxy.pac");
3064 MockAsyncProxyResolver resolver;
3066 ProxyService service(
3067 config_service,
3068 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
3070 GURL url("http://www.google.com/");
3072 ProxyInfo info;
3073 info.UseDirect();
3074 BoundTestNetLog log;
3076 bool synchronous_success = service.TryResolveProxySynchronously(
3077 url, LOAD_NORMAL, &info, NULL, log.bound());
3078 EXPECT_FALSE(synchronous_success);
3080 // No request should have been queued.
3081 EXPECT_EQ(0u, resolver.pending_requests().size());
3083 // |info| should not have been modified.
3084 EXPECT_TRUE(info.is_direct());
3087 // Test that synchronous results are returned correctly if a fixed proxy
3088 // configuration is active.
3089 TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) {
3090 ProxyConfig config;
3091 config.proxy_rules().ParseFromString("foopy1:8080");
3092 config.set_auto_detect(false);
3094 MockAsyncProxyResolver resolver;
3096 ProxyService service(
3097 new MockProxyConfigService(config),
3098 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), NULL);
3100 GURL url("http://www.google.com/");
3102 ProxyInfo info;
3103 BoundTestNetLog log;
3105 bool synchronous_success = service.TryResolveProxySynchronously(
3106 url, LOAD_NORMAL, &info, NULL, log.bound());
3107 EXPECT_TRUE(synchronous_success);
3108 EXPECT_FALSE(info.is_direct());
3109 EXPECT_EQ("foopy1", info.proxy_server().host_port_pair().host());
3111 // No request should have been queued.
3112 EXPECT_EQ(0u, resolver.pending_requests().size());
3115 } // namespace net