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"
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/net_errors.h"
14 #include "net/base/net_log.h"
15 #include "net/base/net_log_unittest.h"
16 #include "net/base/test_completion_callback.h"
17 #include "net/proxy/dhcp_proxy_script_fetcher.h"
18 #include "net/proxy/mock_proxy_resolver.h"
19 #include "net/proxy/mock_proxy_script_fetcher.h"
20 #include "net/proxy/proxy_config_service.h"
21 #include "net/proxy/proxy_resolver.h"
22 #include "net/proxy/proxy_script_fetcher.h"
23 #include "testing/gtest/include/gtest/gtest.h"
26 // TODO(eroman): Write a test which exercises
27 // ProxyService::SuspendAllPendingRequests().
31 // This polling policy will decide to poll every 1 ms.
32 class ImmediatePollPolicy : public ProxyService::PacPollPolicy {
34 ImmediatePollPolicy() {}
36 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
37 base::TimeDelta* next_delay) const OVERRIDE {
38 *next_delay = base::TimeDelta::FromMilliseconds(1);
39 return MODE_USE_TIMER;
43 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy);
46 // This polling policy chooses a fantastically large delay. In other words, it
47 // will never trigger a poll
48 class NeverPollPolicy : public ProxyService::PacPollPolicy {
52 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
53 base::TimeDelta* next_delay) const OVERRIDE {
54 *next_delay = base::TimeDelta::FromDays(60);
55 return MODE_USE_TIMER;
59 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy);
62 // This polling policy starts a poll immediately after network activity.
63 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
65 ImmediateAfterActivityPollPolicy() {}
67 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
68 base::TimeDelta* next_delay) const OVERRIDE {
69 *next_delay = base::TimeDelta();
70 return MODE_START_AFTER_ACTIVITY;
74 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy);
77 // This test fixture is used to partially disable the background polling done by
78 // the ProxyService (which it uses to detect whenever its PAC script contents or
79 // WPAD results have changed).
81 // We disable the feature by setting the poll interval to something really
82 // large, so it will never actually be reached even on the slowest bots that run
85 // We disable the polling in order to avoid any timing dependencies in the
86 // tests. If the bot were to run the tests very slowly and we hadn't disabled
87 // polling, then it might start a background re-try in the middle of our test
88 // and confuse our expectations leading to flaky failures.
90 // The tests which verify the polling code re-enable the polling behavior but
91 // are careful to avoid timing problems.
92 class ProxyServiceTest : public testing::Test {
94 virtual void SetUp() OVERRIDE {
95 testing::Test::SetUp();
97 ProxyService::set_pac_script_poll_policy(&never_poll_policy_);
100 virtual void TearDown() OVERRIDE {
101 // Restore the original policy.
102 ProxyService::set_pac_script_poll_policy(previous_policy_);
103 testing::Test::TearDown();
107 NeverPollPolicy never_poll_policy_;
108 const ProxyService::PacPollPolicy* previous_policy_;
111 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
112 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
114 class MockProxyConfigService: public ProxyConfigService {
116 explicit MockProxyConfigService(const ProxyConfig& config)
117 : availability_(CONFIG_VALID),
121 explicit MockProxyConfigService(const std::string& pac_url)
122 : availability_(CONFIG_VALID),
123 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) {
126 virtual void AddObserver(Observer* observer) OVERRIDE {
127 observers_.AddObserver(observer);
130 virtual void RemoveObserver(Observer* observer) OVERRIDE {
131 observers_.RemoveObserver(observer);
134 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* results)
136 if (availability_ == CONFIG_VALID)
138 return availability_;
141 void SetConfig(const ProxyConfig& config) {
142 availability_ = CONFIG_VALID;
144 FOR_EACH_OBSERVER(Observer, observers_,
145 OnProxyConfigChanged(config_, availability_));
149 ConfigAvailability availability_;
151 ObserverList<Observer, true> observers_;
156 TEST_F(ProxyServiceTest, Direct) {
157 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
158 ProxyService service(new MockProxyConfigService(
159 ProxyConfig::CreateDirect()), resolver, NULL);
161 GURL url("http://www.google.com/");
164 TestCompletionCallback callback;
165 CapturingBoundNetLog log;
166 int rv = service.ResolveProxy(
167 url, &info, callback.callback(), NULL, log.bound());
169 EXPECT_TRUE(resolver->pending_requests().empty());
171 EXPECT_TRUE(info.is_direct());
172 EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
173 EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
175 // Check the NetLog was filled correctly.
176 CapturingNetLog::CapturedEntryList entries;
177 log.GetEntries(&entries);
179 EXPECT_EQ(3u, entries.size());
180 EXPECT_TRUE(LogContainsBeginEvent(
181 entries, 0, NetLog::TYPE_PROXY_SERVICE));
182 EXPECT_TRUE(LogContainsEvent(
183 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
184 NetLog::PHASE_NONE));
185 EXPECT_TRUE(LogContainsEndEvent(
186 entries, 2, NetLog::TYPE_PROXY_SERVICE));
189 TEST_F(ProxyServiceTest, PAC) {
190 MockProxyConfigService* config_service =
191 new MockProxyConfigService("http://foopy/proxy.pac");
193 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
195 ProxyService service(config_service, resolver, NULL);
197 GURL url("http://www.google.com/");
200 TestCompletionCallback callback;
201 ProxyService::PacRequest* request;
202 CapturingBoundNetLog log;
204 int rv = service.ResolveProxy(
205 url, &info, callback.callback(), &request, log.bound());
206 EXPECT_EQ(ERR_IO_PENDING, rv);
208 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request));
210 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
211 resolver->pending_set_pac_script_request()->script_data()->url());
212 resolver->pending_set_pac_script_request()->CompleteNow(OK);
214 ASSERT_EQ(1u, resolver->pending_requests().size());
215 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
217 // Set the result in proxy resolver.
218 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
219 resolver->pending_requests()[0]->CompleteNow(OK);
221 EXPECT_EQ(OK, callback.WaitForResult());
222 EXPECT_FALSE(info.is_direct());
223 EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
224 EXPECT_TRUE(info.did_use_pac_script());
226 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
227 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
228 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
230 // Check the NetLog was filled correctly.
231 CapturingNetLog::CapturedEntryList entries;
232 log.GetEntries(&entries);
234 EXPECT_EQ(5u, entries.size());
235 EXPECT_TRUE(LogContainsBeginEvent(
236 entries, 0, NetLog::TYPE_PROXY_SERVICE));
237 EXPECT_TRUE(LogContainsBeginEvent(
238 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
239 EXPECT_TRUE(LogContainsEndEvent(
240 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
241 EXPECT_TRUE(LogContainsEndEvent(
242 entries, 4, NetLog::TYPE_PROXY_SERVICE));
245 // Test that the proxy resolver does not see the URL's username/password
246 // or its reference section.
247 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) {
248 MockProxyConfigService* config_service =
249 new MockProxyConfigService("http://foopy/proxy.pac");
251 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
253 ProxyService service(config_service, resolver, NULL);
255 GURL url("http://username:password@www.google.com/?ref#hash#hash");
258 TestCompletionCallback callback;
259 int rv = service.ResolveProxy(
260 url, &info, callback.callback(), NULL, BoundNetLog());
261 EXPECT_EQ(ERR_IO_PENDING, rv);
263 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
264 resolver->pending_set_pac_script_request()->script_data()->url());
265 resolver->pending_set_pac_script_request()->CompleteNow(OK);
267 ASSERT_EQ(1u, resolver->pending_requests().size());
268 // The URL should have been simplified, stripping the username/password/hash.
269 EXPECT_EQ(GURL("http://www.google.com/?ref"),
270 resolver->pending_requests()[0]->url());
272 // We end here without ever completing the request -- destruction of
273 // ProxyService will cancel the outstanding request.
276 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
277 MockProxyConfigService* config_service =
278 new MockProxyConfigService("http://foopy/proxy.pac");
279 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
281 ProxyService service(config_service, resolver, NULL);
283 GURL url("http://www.google.com/");
286 TestCompletionCallback callback1;
287 int rv = service.ResolveProxy(
288 url, &info, callback1.callback(), NULL, BoundNetLog());
289 EXPECT_EQ(ERR_IO_PENDING, rv);
291 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
292 resolver->pending_set_pac_script_request()->script_data()->url());
293 resolver->pending_set_pac_script_request()->CompleteNow(OK);
295 ASSERT_EQ(1u, resolver->pending_requests().size());
296 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
298 // Set the result in proxy resolver.
299 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
300 resolver->pending_requests()[0]->CompleteNow(OK);
302 EXPECT_EQ(OK, callback1.WaitForResult());
303 EXPECT_FALSE(info.is_direct());
304 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
305 EXPECT_TRUE(info.did_use_pac_script());
307 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
308 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
309 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
311 // Now, imagine that connecting to foopy:8080 fails: there is nothing
312 // left to fallback to, since our proxy list was NOT terminated by
314 TestCompletionCallback callback2;
315 rv = service.ReconsiderProxyAfterError(
316 url, &info, callback2.callback(), NULL, BoundNetLog());
317 // ReconsiderProxyAfterError returns error indicating nothing left.
318 EXPECT_EQ(ERR_FAILED, rv);
319 EXPECT_TRUE(info.is_empty());
322 // Test that if the execution of the PAC script fails (i.e. javascript runtime
323 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
324 TEST_F(ProxyServiceTest, PAC_RuntimeError) {
325 MockProxyConfigService* config_service =
326 new MockProxyConfigService("http://foopy/proxy.pac");
327 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
329 ProxyService service(config_service, resolver, NULL);
331 GURL url("http://this-causes-js-error/");
334 TestCompletionCallback callback1;
335 int rv = service.ResolveProxy(
336 url, &info, callback1.callback(), NULL, BoundNetLog());
337 EXPECT_EQ(ERR_IO_PENDING, rv);
339 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
340 resolver->pending_set_pac_script_request()->script_data()->url());
341 resolver->pending_set_pac_script_request()->CompleteNow(OK);
343 ASSERT_EQ(1u, resolver->pending_requests().size());
344 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
346 // Simulate a failure in the PAC executor.
347 resolver->pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
349 EXPECT_EQ(OK, callback1.WaitForResult());
351 // Since the PAC script was non-mandatory, we should have fallen-back to
353 EXPECT_TRUE(info.is_direct());
354 EXPECT_TRUE(info.did_use_pac_script());
355 EXPECT_EQ(1, info.config_id());
357 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
358 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
359 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
362 // The proxy list could potentially contain the DIRECT fallback choice
363 // in a location other than the very end of the list, and could even
364 // specify it multiple times.
366 // This is not a typical usage, but we will obey it.
367 // (If we wanted to disallow this type of input, the right place to
368 // enforce it would be in parsing the PAC result string).
370 // This test will use the PAC result string:
372 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
374 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
375 // then foobar:20, and then give up and error.
377 // The important check of this test is to make sure that DIRECT is not somehow
378 // cached as being a bad proxy.
379 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
380 MockProxyConfigService* config_service =
381 new MockProxyConfigService("http://foopy/proxy.pac");
382 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
384 ProxyService service(config_service, resolver, NULL);
386 GURL url("http://www.google.com/");
389 TestCompletionCallback callback1;
390 int rv = service.ResolveProxy(
391 url, &info, callback1.callback(), NULL, BoundNetLog());
392 EXPECT_EQ(ERR_IO_PENDING, rv);
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()->UsePacString(
403 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
404 resolver->pending_requests()[0]->CompleteNow(OK);
406 EXPECT_EQ(OK, callback1.WaitForResult());
407 EXPECT_TRUE(info.is_direct());
410 TestCompletionCallback callback2;
411 rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL,
414 EXPECT_FALSE(info.is_direct());
415 EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
418 TestCompletionCallback callback3;
419 rv = service.ReconsiderProxyAfterError(url, &info, callback3.callback(), NULL,
422 EXPECT_TRUE(info.is_direct());
425 TestCompletionCallback callback4;
426 rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL,
429 EXPECT_FALSE(info.is_direct());
430 EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
432 // Fallback 4 -- Nothing to fall back to!
433 TestCompletionCallback callback5;
434 rv = service.ReconsiderProxyAfterError(url, &info, callback5.callback(), NULL,
436 EXPECT_EQ(ERR_FAILED, rv);
437 EXPECT_TRUE(info.is_empty());
440 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
441 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
442 // to ProxyInfo after the proxy is resolved via a PAC script.
444 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
445 config.set_source(PROXY_CONFIG_SOURCE_TEST);
447 MockProxyConfigService* config_service = new MockProxyConfigService(config);
448 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
449 ProxyService service(config_service, resolver, NULL);
451 // Resolve something.
452 GURL url("http://www.google.com/");
454 TestCompletionCallback callback;
455 int rv = service.ResolveProxy(
456 url, &info, callback.callback(), NULL, BoundNetLog());
457 ASSERT_EQ(ERR_IO_PENDING, rv);
458 resolver->pending_set_pac_script_request()->CompleteNow(OK);
459 ASSERT_EQ(1u, resolver->pending_requests().size());
461 // Set the result in proxy resolver.
462 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
463 resolver->pending_requests()[0]->CompleteNow(OK);
465 EXPECT_EQ(OK, callback.WaitForResult());
466 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
467 EXPECT_TRUE(info.did_use_pac_script());
469 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
470 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
471 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
474 TEST_F(ProxyServiceTest, ProxyResolverFails) {
475 // Test what happens when the ProxyResolver fails. The download and setting
476 // of the PAC script have already succeeded, so this corresponds with a
477 // javascript runtime error while calling FindProxyForURL().
479 MockProxyConfigService* config_service =
480 new MockProxyConfigService("http://foopy/proxy.pac");
482 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
484 ProxyService service(config_service, resolver, NULL);
486 // Start first resolve request.
487 GURL url("http://www.google.com/");
489 TestCompletionCallback callback1;
490 int rv = service.ResolveProxy(
491 url, &info, callback1.callback(), NULL, BoundNetLog());
492 EXPECT_EQ(ERR_IO_PENDING, rv);
494 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
495 resolver->pending_set_pac_script_request()->script_data()->url());
496 resolver->pending_set_pac_script_request()->CompleteNow(OK);
498 ASSERT_EQ(1u, resolver->pending_requests().size());
499 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
501 // Fail the first resolve request in MockAsyncProxyResolver.
502 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
504 // Although the proxy resolver failed the request, ProxyService implicitly
505 // falls-back to DIRECT.
506 EXPECT_EQ(OK, callback1.WaitForResult());
507 EXPECT_TRUE(info.is_direct());
509 // Failed PAC executions still have proxy resolution times.
510 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
511 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
512 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
514 // The second resolve request will try to run through the proxy resolver,
515 // regardless of whether the first request failed in it.
516 TestCompletionCallback callback2;
517 rv = service.ResolveProxy(
518 url, &info, callback2.callback(), NULL, BoundNetLog());
519 EXPECT_EQ(ERR_IO_PENDING, rv);
521 ASSERT_EQ(1u, resolver->pending_requests().size());
522 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
524 // This time we will have the resolver succeed (perhaps the PAC script has
525 // a dependency on the current time).
526 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
527 resolver->pending_requests()[0]->CompleteNow(OK);
529 EXPECT_EQ(OK, callback2.WaitForResult());
530 EXPECT_FALSE(info.is_direct());
531 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
534 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
535 // Test what happens when the ProxyScriptResolver fails to download a
536 // mandatory PAC script.
539 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
540 config.set_pac_mandatory(true);
542 MockProxyConfigService* config_service = new MockProxyConfigService(config);
544 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
546 ProxyService service(config_service, resolver, NULL);
548 // Start first resolve request.
549 GURL url("http://www.google.com/");
551 TestCompletionCallback callback1;
552 int rv = service.ResolveProxy(
553 url, &info, callback1.callback(), NULL, BoundNetLog());
554 EXPECT_EQ(ERR_IO_PENDING, rv);
556 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
557 resolver->pending_set_pac_script_request()->script_data()->url());
558 resolver->pending_set_pac_script_request()->CompleteNow(ERR_FAILED);
560 ASSERT_EQ(0u, resolver->pending_requests().size());
562 // As the proxy resolver failed the request and is configured for a mandatory
563 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
564 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
565 callback1.WaitForResult());
566 EXPECT_FALSE(info.is_direct());
568 // As the proxy resolver failed the request and is configured for a mandatory
569 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
570 TestCompletionCallback callback2;
571 rv = service.ResolveProxy(
572 url, &info, callback2.callback(), NULL, BoundNetLog());
573 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
574 EXPECT_FALSE(info.is_direct());
577 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
578 // Test what happens when the ProxyResolver fails that is configured to use a
579 // mandatory PAC script. The download of the PAC script has already
580 // succeeded but the PAC script contains no valid javascript.
583 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
584 config.set_pac_mandatory(true);
586 MockProxyConfigService* config_service = new MockProxyConfigService(config);
588 MockAsyncProxyResolverExpectsBytes* resolver =
589 new MockAsyncProxyResolverExpectsBytes;
591 ProxyService service(config_service, resolver, NULL);
593 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
594 DhcpProxyScriptFetcher* dhcp_fetcher = new DoNothingDhcpProxyScriptFetcher();
595 service.SetProxyScriptFetchers(fetcher, dhcp_fetcher);
597 // Start resolve request.
598 GURL url("http://www.google.com/");
600 TestCompletionCallback callback;
601 int rv = service.ResolveProxy(
602 url, &info, callback.callback(), NULL, BoundNetLog());
603 EXPECT_EQ(ERR_IO_PENDING, rv);
605 // Check that nothing has been sent to the proxy resolver yet.
606 ASSERT_EQ(0u, resolver->pending_requests().size());
608 // Downloading the PAC script succeeds.
609 EXPECT_TRUE(fetcher->has_pending_request());
610 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
611 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
613 EXPECT_FALSE(fetcher->has_pending_request());
614 ASSERT_EQ(0u, resolver->pending_requests().size());
616 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
617 // mandatory for this configuration, the ProxyService must not implicitly
618 // fall-back to DIRECT.
619 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
620 callback.WaitForResult());
621 EXPECT_FALSE(info.is_direct());
624 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
625 // Test what happens when the ProxyResolver fails that is configured to use a
626 // mandatory PAC script. The download and setting of the PAC script have
627 // already succeeded, so this corresponds with a javascript runtime error
628 // while calling FindProxyForURL().
631 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
632 config.set_pac_mandatory(true);
634 MockProxyConfigService* config_service = new MockProxyConfigService(config);
636 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
638 ProxyService service(config_service, resolver, NULL);
640 // Start first resolve request.
641 GURL url("http://www.google.com/");
643 TestCompletionCallback callback1;
644 int rv = service.ResolveProxy(
645 url, &info, callback1.callback(), NULL, BoundNetLog());
646 EXPECT_EQ(ERR_IO_PENDING, rv);
648 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
649 resolver->pending_set_pac_script_request()->script_data()->url());
650 resolver->pending_set_pac_script_request()->CompleteNow(OK);
652 ASSERT_EQ(1u, resolver->pending_requests().size());
653 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
655 // Fail the first resolve request in MockAsyncProxyResolver.
656 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
658 // As the proxy resolver failed the request and is configured for a mandatory
659 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
660 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
661 callback1.WaitForResult());
662 EXPECT_FALSE(info.is_direct());
664 // The second resolve request will try to run through the proxy resolver,
665 // regardless of whether the first request failed in it.
666 TestCompletionCallback callback2;
667 rv = service.ResolveProxy(
668 url, &info, callback2.callback(), NULL, BoundNetLog());
669 EXPECT_EQ(ERR_IO_PENDING, rv);
671 ASSERT_EQ(1u, resolver->pending_requests().size());
672 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
674 // This time we will have the resolver succeed (perhaps the PAC script has
675 // a dependency on the current time).
676 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
677 resolver->pending_requests()[0]->CompleteNow(OK);
679 EXPECT_EQ(OK, callback2.WaitForResult());
680 EXPECT_FALSE(info.is_direct());
681 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
684 TEST_F(ProxyServiceTest, ProxyFallback) {
685 // Test what happens when we specify multiple proxy servers and some of them
688 MockProxyConfigService* config_service =
689 new MockProxyConfigService("http://foopy/proxy.pac");
691 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
693 ProxyService service(config_service, resolver, NULL);
695 GURL url("http://www.google.com/");
697 // Get the proxy information.
699 TestCompletionCallback callback1;
700 int rv = service.ResolveProxy(
701 url, &info, callback1.callback(), NULL, BoundNetLog());
702 EXPECT_EQ(ERR_IO_PENDING, rv);
704 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
705 resolver->pending_set_pac_script_request()->script_data()->url());
706 resolver->pending_set_pac_script_request()->CompleteNow(OK);
708 ASSERT_EQ(1u, resolver->pending_requests().size());
709 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
711 // Set the result in proxy resolver.
712 resolver->pending_requests()[0]->results()->UseNamedProxy(
713 "foopy1:8080;foopy2:9090");
714 resolver->pending_requests()[0]->CompleteNow(OK);
716 // The first item is valid.
717 EXPECT_EQ(OK, callback1.WaitForResult());
718 EXPECT_FALSE(info.is_direct());
719 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
721 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
722 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
723 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
724 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
725 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
727 // Fake an error on the proxy.
728 TestCompletionCallback callback2;
729 rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL,
733 // Proxy times should not have been modified by fallback.
734 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
735 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
737 // The second proxy should be specified.
738 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
739 // Report back that the second proxy worked. This will globally mark the
740 // first proxy as bad.
741 service.ReportSuccess(info);
743 TestCompletionCallback callback3;
744 rv = service.ResolveProxy(
745 url, &info, callback3.callback(), NULL, BoundNetLog());
746 EXPECT_EQ(ERR_IO_PENDING, rv);
748 ASSERT_EQ(1u, resolver->pending_requests().size());
749 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
751 // Set the result in proxy resolver -- the second result is already known
752 // to be bad, so we will not try to use it initially.
753 resolver->pending_requests()[0]->results()->UseNamedProxy(
754 "foopy3:7070;foopy1:8080;foopy2:9090");
755 resolver->pending_requests()[0]->CompleteNow(OK);
757 EXPECT_EQ(OK, callback3.WaitForResult());
758 EXPECT_FALSE(info.is_direct());
759 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
761 // Proxy times should have been updated, so get them again.
762 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
763 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
764 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
765 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
766 proxy_resolve_start_time = info.proxy_resolve_start_time();
767 proxy_resolve_end_time = info.proxy_resolve_end_time();
769 // We fake another error. It should now try the third one.
770 TestCompletionCallback callback4;
771 rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL,
774 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
776 // We fake another error. At this point we have tried all of the
777 // proxy servers we thought were valid; next we try the proxy server
778 // that was in our bad proxies map (foopy1:8080).
779 TestCompletionCallback callback5;
780 rv = service.ReconsiderProxyAfterError(url, &info, callback5.callback(), NULL,
783 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
785 // Fake another error, the last proxy is gone, the list should now be empty,
786 // so there is nothing left to try.
787 TestCompletionCallback callback6;
788 rv = service.ReconsiderProxyAfterError(url, &info, callback6.callback(), NULL,
790 EXPECT_EQ(ERR_FAILED, rv);
791 EXPECT_FALSE(info.is_direct());
792 EXPECT_TRUE(info.is_empty());
794 // Proxy times should not have been modified by fallback.
795 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
796 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
798 // Look up proxies again
799 TestCompletionCallback callback7;
800 rv = service.ResolveProxy(url, &info, callback7.callback(), NULL,
802 EXPECT_EQ(ERR_IO_PENDING, rv);
804 ASSERT_EQ(1u, resolver->pending_requests().size());
805 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
807 // This time, the first 3 results have been found to be bad, but only the
808 // first proxy has been confirmed ...
809 resolver->pending_requests()[0]->results()->UseNamedProxy(
810 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
811 resolver->pending_requests()[0]->CompleteNow(OK);
813 // ... therefore, we should see the second proxy first.
814 EXPECT_EQ(OK, callback7.WaitForResult());
815 EXPECT_FALSE(info.is_direct());
816 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
818 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
819 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
820 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
821 // TODO(nsylvain): Test that the proxy can be retried after the delay.
824 // This test is similar to ProxyFallback, but this time we have an explicit
825 // fallback choice to DIRECT.
826 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
827 MockProxyConfigService* config_service =
828 new MockProxyConfigService("http://foopy/proxy.pac");
830 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
832 ProxyService service(config_service, resolver, NULL);
834 GURL url("http://www.google.com/");
836 // Get the proxy information.
838 TestCompletionCallback callback1;
839 int rv = service.ResolveProxy(
840 url, &info, callback1.callback(), NULL, BoundNetLog());
841 EXPECT_EQ(ERR_IO_PENDING, rv);
843 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
844 resolver->pending_set_pac_script_request()->script_data()->url());
845 resolver->pending_set_pac_script_request()->CompleteNow(OK);
847 ASSERT_EQ(1u, resolver->pending_requests().size());
848 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
850 // Set the result in proxy resolver.
851 resolver->pending_requests()[0]->results()->UsePacString(
852 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
853 resolver->pending_requests()[0]->CompleteNow(OK);
855 // Get the first result.
856 EXPECT_EQ(OK, callback1.WaitForResult());
857 EXPECT_FALSE(info.is_direct());
858 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
860 // Fake an error on the proxy.
861 TestCompletionCallback callback2;
862 rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL,
866 // Now we get back the second proxy.
867 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
869 // Fake an error on this proxy as well.
870 TestCompletionCallback callback3;
871 rv = service.ReconsiderProxyAfterError(url, &info, callback3.callback(), NULL,
875 // Finally, we get back DIRECT.
876 EXPECT_TRUE(info.is_direct());
878 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
879 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
880 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
882 // Now we tell the proxy service that even DIRECT failed.
883 TestCompletionCallback callback4;
884 rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL,
886 // There was nothing left to try after DIRECT, so we are out of
888 EXPECT_EQ(ERR_FAILED, rv);
891 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
892 // Test proxy failover when new settings are available.
894 MockProxyConfigService* config_service =
895 new MockProxyConfigService("http://foopy/proxy.pac");
897 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
899 ProxyService service(config_service, resolver, NULL);
901 GURL url("http://www.google.com/");
903 // Get the proxy information.
905 TestCompletionCallback callback1;
906 int rv = service.ResolveProxy(
907 url, &info, callback1.callback(), NULL, BoundNetLog());
908 EXPECT_EQ(ERR_IO_PENDING, rv);
910 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
911 resolver->pending_set_pac_script_request()->script_data()->url());
912 resolver->pending_set_pac_script_request()->CompleteNow(OK);
914 ASSERT_EQ(1u, resolver->pending_requests().size());
915 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
917 // Set the result in proxy resolver.
918 resolver->pending_requests()[0]->results()->UseNamedProxy(
919 "foopy1:8080;foopy2:9090");
920 resolver->pending_requests()[0]->CompleteNow(OK);
922 // The first item is valid.
923 EXPECT_EQ(OK, callback1.WaitForResult());
924 EXPECT_FALSE(info.is_direct());
925 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
927 // Fake an error on the proxy, and also a new configuration on the proxy.
928 config_service->SetConfig(
929 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
931 TestCompletionCallback callback2;
932 rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL,
934 EXPECT_EQ(ERR_IO_PENDING, rv);
936 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
937 resolver->pending_set_pac_script_request()->script_data()->url());
938 resolver->pending_set_pac_script_request()->CompleteNow(OK);
940 ASSERT_EQ(1u, resolver->pending_requests().size());
941 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
943 resolver->pending_requests()[0]->results()->UseNamedProxy(
944 "foopy1:8080;foopy2:9090");
945 resolver->pending_requests()[0]->CompleteNow(OK);
947 // The first proxy is still there since the configuration changed.
948 EXPECT_EQ(OK, callback2.WaitForResult());
949 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
951 // We fake another error. It should now ignore the first one.
952 TestCompletionCallback callback3;
953 rv = service.ReconsiderProxyAfterError(url, &info, callback3.callback(), NULL,
956 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
958 // We simulate a new configuration.
959 config_service->SetConfig(
960 ProxyConfig::CreateFromCustomPacURL(
961 GURL("http://foopy-new2/proxy.pac")));
963 // We fake another error. It should go back to the first proxy.
964 TestCompletionCallback callback4;
965 rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL,
967 EXPECT_EQ(ERR_IO_PENDING, rv);
969 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
970 resolver->pending_set_pac_script_request()->script_data()->url());
971 resolver->pending_set_pac_script_request()->CompleteNow(OK);
973 ASSERT_EQ(1u, resolver->pending_requests().size());
974 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
976 resolver->pending_requests()[0]->results()->UseNamedProxy(
977 "foopy1:8080;foopy2:9090");
978 resolver->pending_requests()[0]->CompleteNow(OK);
980 EXPECT_EQ(OK, callback4.WaitForResult());
981 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
983 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
984 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
985 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
988 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
989 // Test proxy failover when the configuration is bad.
991 MockProxyConfigService* config_service =
992 new MockProxyConfigService("http://foopy/proxy.pac");
994 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
996 ProxyService service(config_service, resolver, NULL);
998 GURL url("http://www.google.com/");
1000 // Get the proxy information.
1002 TestCompletionCallback callback1;
1003 int rv = service.ResolveProxy(
1004 url, &info, callback1.callback(), NULL, BoundNetLog());
1005 EXPECT_EQ(ERR_IO_PENDING, rv);
1007 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1008 resolver->pending_set_pac_script_request()->script_data()->url());
1009 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1010 ASSERT_EQ(1u, resolver->pending_requests().size());
1011 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1013 resolver->pending_requests()[0]->results()->UseNamedProxy(
1014 "foopy1:8080;foopy2:9090");
1015 resolver->pending_requests()[0]->CompleteNow(OK);
1017 // The first item is valid.
1018 EXPECT_EQ(OK, callback1.WaitForResult());
1019 EXPECT_FALSE(info.is_direct());
1020 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1022 // Fake a proxy error.
1023 TestCompletionCallback callback2;
1024 rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL,
1028 // The first proxy is ignored, and the second one is selected.
1029 EXPECT_FALSE(info.is_direct());
1030 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1032 // Fake a PAC failure.
1034 TestCompletionCallback callback3;
1035 rv = service.ResolveProxy(
1036 url, &info2, callback3.callback(), NULL, BoundNetLog());
1037 EXPECT_EQ(ERR_IO_PENDING, rv);
1039 ASSERT_EQ(1u, resolver->pending_requests().size());
1040 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1042 // This simulates a javascript runtime error in the PAC script.
1043 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
1045 // Although the resolver failed, the ProxyService will implicitly fall-back
1046 // to a DIRECT connection.
1047 EXPECT_EQ(OK, callback3.WaitForResult());
1048 EXPECT_TRUE(info2.is_direct());
1049 EXPECT_FALSE(info2.is_empty());
1051 // The PAC script will work properly next time and successfully return a
1052 // proxy list. Since we have not marked the configuration as bad, it should
1053 // "just work" the next time we call it.
1055 TestCompletionCallback callback4;
1056 rv = service.ReconsiderProxyAfterError(url, &info3, callback4.callback(),
1057 NULL, BoundNetLog());
1058 EXPECT_EQ(ERR_IO_PENDING, rv);
1060 ASSERT_EQ(1u, resolver->pending_requests().size());
1061 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1063 resolver->pending_requests()[0]->results()->UseNamedProxy(
1064 "foopy1:8080;foopy2:9090");
1065 resolver->pending_requests()[0]->CompleteNow(OK);
1067 // The first proxy is not there since the it was added to the bad proxies
1068 // list by the earlier ReconsiderProxyAfterError().
1069 EXPECT_EQ(OK, callback4.WaitForResult());
1070 EXPECT_FALSE(info3.is_direct());
1071 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1073 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1074 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1075 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1078 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
1079 // Test proxy failover when the configuration is bad.
1082 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1084 config.set_pac_mandatory(true);
1085 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1087 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1089 ProxyService service(config_service, resolver, NULL);
1091 GURL url("http://www.google.com/");
1093 // Get the proxy information.
1095 TestCompletionCallback callback1;
1096 int rv = service.ResolveProxy(
1097 url, &info, callback1.callback(), NULL, BoundNetLog());
1098 EXPECT_EQ(ERR_IO_PENDING, rv);
1100 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1101 resolver->pending_set_pac_script_request()->script_data()->url());
1102 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1103 ASSERT_EQ(1u, resolver->pending_requests().size());
1104 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1106 resolver->pending_requests()[0]->results()->UseNamedProxy(
1107 "foopy1:8080;foopy2:9090");
1108 resolver->pending_requests()[0]->CompleteNow(OK);
1110 // The first item is valid.
1111 EXPECT_EQ(OK, callback1.WaitForResult());
1112 EXPECT_FALSE(info.is_direct());
1113 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1115 // Fake a proxy error.
1116 TestCompletionCallback callback2;
1117 rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL,
1121 // The first proxy is ignored, and the second one is selected.
1122 EXPECT_FALSE(info.is_direct());
1123 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1125 // Fake a PAC failure.
1127 TestCompletionCallback callback3;
1128 rv = service.ResolveProxy(
1129 url, &info2, callback3.callback(), NULL, BoundNetLog());
1130 EXPECT_EQ(ERR_IO_PENDING, rv);
1132 ASSERT_EQ(1u, resolver->pending_requests().size());
1133 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1135 // This simulates a javascript runtime error in the PAC script.
1136 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
1138 // Although the resolver failed, the ProxyService will NOT fall-back
1139 // to a DIRECT connection as it is configured as mandatory.
1140 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1141 callback3.WaitForResult());
1142 EXPECT_FALSE(info2.is_direct());
1143 EXPECT_TRUE(info2.is_empty());
1145 // The PAC script will work properly next time and successfully return a
1146 // proxy list. Since we have not marked the configuration as bad, it should
1147 // "just work" the next time we call it.
1149 TestCompletionCallback callback4;
1150 rv = service.ReconsiderProxyAfterError(url, &info3, callback4.callback(),
1151 NULL, BoundNetLog());
1152 EXPECT_EQ(ERR_IO_PENDING, rv);
1154 ASSERT_EQ(1u, resolver->pending_requests().size());
1155 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1157 resolver->pending_requests()[0]->results()->UseNamedProxy(
1158 "foopy1:8080;foopy2:9090");
1159 resolver->pending_requests()[0]->CompleteNow(OK);
1161 // The first proxy is not there since the it was added to the bad proxies
1162 // list by the earlier ReconsiderProxyAfterError().
1163 EXPECT_EQ(OK, callback4.WaitForResult());
1164 EXPECT_FALSE(info3.is_direct());
1165 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1168 TEST_F(ProxyServiceTest, ProxyBypassList) {
1169 // Test that the proxy bypass rules are consulted.
1171 TestCompletionCallback callback[2];
1174 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1175 config.set_auto_detect(false);
1176 config.proxy_rules().bypass_rules.ParseFromString("*.org");
1178 ProxyService service(
1179 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1182 GURL url1("http://www.webkit.org");
1183 GURL url2("http://www.webkit.com");
1185 // Request for a .org domain should bypass proxy.
1186 rv = service.ResolveProxy(
1187 url1, &info[0], callback[0].callback(), NULL, BoundNetLog());
1189 EXPECT_TRUE(info[0].is_direct());
1191 // Request for a .com domain hits the proxy.
1192 rv = service.ResolveProxy(
1193 url2, &info[1], callback[1].callback(), NULL, BoundNetLog());
1195 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
1199 TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
1201 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1202 config.set_auto_detect(false);
1204 ProxyService service(
1205 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1206 GURL test_url("http://www.msn.com");
1208 TestCompletionCallback callback;
1209 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1212 EXPECT_FALSE(info.is_direct());
1213 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1216 ProxyService service(
1217 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1218 GURL test_url("ftp://ftp.google.com");
1220 TestCompletionCallback callback;
1221 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1224 EXPECT_TRUE(info.is_direct());
1225 EXPECT_EQ("direct://", info.proxy_server().ToURI());
1228 ProxyService service(
1229 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1230 GURL test_url("https://webbranch.techcu.com");
1232 TestCompletionCallback callback;
1233 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1236 EXPECT_FALSE(info.is_direct());
1237 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
1240 config.proxy_rules().ParseFromString("foopy1:8080");
1241 ProxyService service(
1242 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1243 GURL test_url("http://www.microsoft.com");
1245 TestCompletionCallback callback;
1246 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1249 EXPECT_FALSE(info.is_direct());
1250 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1254 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
1255 // Test that the proxy config source is set correctly when resolving proxies
1256 // using manual proxy rules. Namely, the config source should only be set if
1257 // any of the rules were applied.
1260 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1261 config.proxy_rules().ParseFromString("https=foopy2:8080");
1262 ProxyService service(
1263 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1264 GURL test_url("http://www.google.com");
1266 TestCompletionCallback callback;
1267 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1270 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1271 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1275 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1276 config.proxy_rules().ParseFromString("https=foopy2:8080");
1277 ProxyService service(
1278 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1279 GURL test_url("https://www.google.com");
1281 TestCompletionCallback callback;
1282 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1285 // Used the HTTPS proxy. So source should be TEST.
1286 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1290 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1291 ProxyService service(
1292 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1293 GURL test_url("http://www.google.com");
1295 TestCompletionCallback callback;
1296 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1299 // ProxyConfig is empty. Source should still be TEST.
1300 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1304 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1305 // fall back to the SOCKS proxy.
1306 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
1308 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1309 config.set_auto_detect(false);
1310 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
1311 config.proxy_rules().type);
1314 ProxyService service(
1315 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1316 GURL test_url("http://www.msn.com");
1318 TestCompletionCallback callback;
1319 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1322 EXPECT_FALSE(info.is_direct());
1323 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1326 ProxyService service(
1327 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1328 GURL test_url("ftp://ftp.google.com");
1330 TestCompletionCallback callback;
1331 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1334 EXPECT_FALSE(info.is_direct());
1335 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1338 ProxyService service(
1339 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1340 GURL test_url("https://webbranch.techcu.com");
1342 TestCompletionCallback callback;
1343 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1346 EXPECT_FALSE(info.is_direct());
1347 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1350 ProxyService service(
1351 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1352 GURL test_url("unknown://www.microsoft.com");
1354 TestCompletionCallback callback;
1355 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1358 EXPECT_FALSE(info.is_direct());
1359 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1363 // Test cancellation of an in-progress request.
1364 TEST_F(ProxyServiceTest, CancelInProgressRequest) {
1365 MockProxyConfigService* config_service =
1366 new MockProxyConfigService("http://foopy/proxy.pac");
1368 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1370 ProxyService service(config_service, resolver, NULL);
1372 // Start 3 requests.
1375 TestCompletionCallback callback1;
1376 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1377 callback1.callback(), NULL, BoundNetLog());
1378 EXPECT_EQ(ERR_IO_PENDING, rv);
1380 // Nothing has been sent to the proxy resolver yet, since the proxy
1381 // resolver has not been configured yet.
1382 ASSERT_EQ(0u, resolver->pending_requests().size());
1384 // Successfully initialize the PAC script.
1385 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1386 resolver->pending_set_pac_script_request()->script_data()->url());
1387 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1389 ASSERT_EQ(1u, resolver->pending_requests().size());
1390 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1393 TestCompletionCallback callback2;
1394 ProxyService::PacRequest* request2;
1395 rv = service.ResolveProxy(GURL("http://request2"), &info2,
1396 callback2.callback(), &request2, BoundNetLog());
1397 EXPECT_EQ(ERR_IO_PENDING, rv);
1398 ASSERT_EQ(2u, resolver->pending_requests().size());
1399 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1402 TestCompletionCallback callback3;
1403 rv = service.ResolveProxy(GURL("http://request3"), &info3,
1404 callback3.callback(), NULL, BoundNetLog());
1405 EXPECT_EQ(ERR_IO_PENDING, rv);
1406 ASSERT_EQ(3u, resolver->pending_requests().size());
1407 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1409 // Cancel the second request
1410 service.CancelPacRequest(request2);
1412 ASSERT_EQ(2u, resolver->pending_requests().size());
1413 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1414 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url());
1416 // Complete the two un-cancelled requests.
1417 // We complete the last one first, just to mix it up a bit.
1418 resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80");
1419 resolver->pending_requests()[1]->CompleteNow(OK);
1421 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1422 resolver->pending_requests()[0]->CompleteNow(OK);
1424 // Complete and verify that requests ran as expected.
1425 EXPECT_EQ(OK, callback1.WaitForResult());
1426 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1428 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1429 ASSERT_EQ(1u, resolver->cancelled_requests().size());
1430 EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url());
1432 EXPECT_EQ(OK, callback3.WaitForResult());
1433 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1436 // Test the initial PAC download for resolver that expects bytes.
1437 TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
1438 MockProxyConfigService* config_service =
1439 new MockProxyConfigService("http://foopy/proxy.pac");
1441 MockAsyncProxyResolverExpectsBytes* resolver =
1442 new MockAsyncProxyResolverExpectsBytes;
1444 ProxyService service(config_service, resolver, NULL);
1446 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1447 service.SetProxyScriptFetchers(fetcher,
1448 new DoNothingDhcpProxyScriptFetcher());
1450 // Start 3 requests.
1453 TestCompletionCallback callback1;
1454 ProxyService::PacRequest* request1;
1455 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1456 callback1.callback(), &request1, BoundNetLog());
1457 EXPECT_EQ(ERR_IO_PENDING, rv);
1459 // The first request should have triggered download of PAC script.
1460 EXPECT_TRUE(fetcher->has_pending_request());
1461 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1464 TestCompletionCallback callback2;
1465 ProxyService::PacRequest* request2;
1466 rv = service.ResolveProxy(GURL("http://request2"), &info2,
1467 callback2.callback(), &request2, BoundNetLog());
1468 EXPECT_EQ(ERR_IO_PENDING, rv);
1471 TestCompletionCallback callback3;
1472 ProxyService::PacRequest* request3;
1473 rv = service.ResolveProxy(GURL("http://request3"), &info3,
1474 callback3.callback(), &request3, BoundNetLog());
1475 EXPECT_EQ(ERR_IO_PENDING, rv);
1477 // Nothing has been sent to the resolver yet.
1478 EXPECT_TRUE(resolver->pending_requests().empty());
1480 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1481 service.GetLoadState(request1));
1482 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1483 service.GetLoadState(request2));
1484 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1485 service.GetLoadState(request3));
1487 // At this point the ProxyService should be waiting for the
1488 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1489 // PAC script download completion.
1490 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1492 // Now that the PAC script is downloaded, it will have been sent to the proxy
1494 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1495 resolver->pending_set_pac_script_request()->script_data()->utf16());
1496 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1498 ASSERT_EQ(3u, resolver->pending_requests().size());
1499 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1500 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1501 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1503 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1));
1504 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2));
1505 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3));
1507 // Complete all the requests (in some order).
1508 // Note that as we complete requests, they shift up in |pending_requests()|.
1510 resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80");
1511 resolver->pending_requests()[2]->CompleteNow(OK);
1513 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1514 resolver->pending_requests()[0]->CompleteNow(OK);
1516 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1517 resolver->pending_requests()[0]->CompleteNow(OK);
1519 // Complete and verify that requests ran as expected.
1520 EXPECT_EQ(OK, callback1.WaitForResult());
1521 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1522 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1523 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1524 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
1526 EXPECT_EQ(OK, callback2.WaitForResult());
1527 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1528 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
1529 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
1530 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
1532 EXPECT_EQ(OK, callback3.WaitForResult());
1533 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1534 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
1535 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
1536 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
1539 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1540 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
1541 MockProxyConfigService* config_service =
1542 new MockProxyConfigService("http://foopy/proxy.pac");
1544 MockAsyncProxyResolverExpectsBytes* resolver =
1545 new MockAsyncProxyResolverExpectsBytes;
1547 ProxyService service(config_service, resolver, NULL);
1549 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1550 service.SetProxyScriptFetchers(fetcher,
1551 new DoNothingDhcpProxyScriptFetcher());
1553 // Start 2 requests.
1556 TestCompletionCallback callback1;
1557 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1558 callback1.callback(), NULL, BoundNetLog());
1559 EXPECT_EQ(ERR_IO_PENDING, rv);
1561 // The first request should have triggered download of PAC script.
1562 EXPECT_TRUE(fetcher->has_pending_request());
1563 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1566 TestCompletionCallback callback2;
1567 rv = service.ResolveProxy(GURL("http://request2"), &info2,
1568 callback2.callback(), NULL, BoundNetLog());
1569 EXPECT_EQ(ERR_IO_PENDING, rv);
1571 // At this point the ProxyService should be waiting for the
1572 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1573 // PAC script download completion.
1575 // We now change out the ProxyService's script fetcher. We should restart
1576 // the initialization with the new fetcher.
1578 fetcher = new MockProxyScriptFetcher;
1579 service.SetProxyScriptFetchers(fetcher,
1580 new DoNothingDhcpProxyScriptFetcher());
1582 // Nothing has been sent to the resolver yet.
1583 EXPECT_TRUE(resolver->pending_requests().empty());
1585 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1587 // Now that the PAC script is downloaded, it will have been sent to the proxy
1589 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1590 resolver->pending_set_pac_script_request()->script_data()->utf16());
1591 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1593 ASSERT_EQ(2u, resolver->pending_requests().size());
1594 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1595 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1598 // Test cancellation of a request, while the PAC script is being fetched.
1599 TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
1600 MockProxyConfigService* config_service =
1601 new MockProxyConfigService("http://foopy/proxy.pac");
1603 MockAsyncProxyResolverExpectsBytes* resolver =
1604 new MockAsyncProxyResolverExpectsBytes;
1606 ProxyService service(config_service, resolver, NULL);
1608 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1609 service.SetProxyScriptFetchers(fetcher,
1610 new DoNothingDhcpProxyScriptFetcher());
1612 // Start 3 requests.
1614 TestCompletionCallback callback1;
1615 ProxyService::PacRequest* request1;
1616 CapturingBoundNetLog log1;
1617 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1618 callback1.callback(), &request1, log1.bound());
1619 EXPECT_EQ(ERR_IO_PENDING, rv);
1621 // The first request should have triggered download of PAC script.
1622 EXPECT_TRUE(fetcher->has_pending_request());
1623 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1626 TestCompletionCallback callback2;
1627 ProxyService::PacRequest* request2;
1628 rv = service.ResolveProxy(GURL("http://request2"), &info2,
1629 callback2.callback(), &request2, BoundNetLog());
1630 EXPECT_EQ(ERR_IO_PENDING, rv);
1633 TestCompletionCallback callback3;
1634 rv = service.ResolveProxy(GURL("http://request3"), &info3,
1635 callback3.callback(), NULL, BoundNetLog());
1636 EXPECT_EQ(ERR_IO_PENDING, rv);
1638 // Nothing has been sent to the resolver yet.
1639 EXPECT_TRUE(resolver->pending_requests().empty());
1641 // Cancel the first 2 requests.
1642 service.CancelPacRequest(request1);
1643 service.CancelPacRequest(request2);
1645 // At this point the ProxyService should be waiting for the
1646 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1647 // PAC script download completion.
1648 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1650 // Now that the PAC script is downloaded, it will have been sent to the
1652 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1653 resolver->pending_set_pac_script_request()->script_data()->utf16());
1654 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1656 ASSERT_EQ(1u, resolver->pending_requests().size());
1657 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url());
1659 // Complete all the requests.
1660 resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80");
1661 resolver->pending_requests()[0]->CompleteNow(OK);
1663 EXPECT_EQ(OK, callback3.WaitForResult());
1664 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1666 EXPECT_TRUE(resolver->cancelled_requests().empty());
1668 EXPECT_FALSE(callback1.have_result()); // Cancelled.
1669 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1671 CapturingNetLog::CapturedEntryList entries1;
1672 log1.GetEntries(&entries1);
1674 // Check the NetLog for request 1 (which was cancelled) got filled properly.
1675 EXPECT_EQ(4u, entries1.size());
1676 EXPECT_TRUE(LogContainsBeginEvent(
1677 entries1, 0, NetLog::TYPE_PROXY_SERVICE));
1678 EXPECT_TRUE(LogContainsBeginEvent(
1679 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
1680 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1681 // the cancellation occured.
1682 EXPECT_TRUE(LogContainsEvent(
1683 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
1684 EXPECT_TRUE(LogContainsEndEvent(
1685 entries1, 3, NetLog::TYPE_PROXY_SERVICE));
1688 // Test that if auto-detect fails, we fall-back to the custom pac.
1689 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
1691 config.set_auto_detect(true);
1692 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1693 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1695 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1696 MockAsyncProxyResolverExpectsBytes* resolver =
1697 new MockAsyncProxyResolverExpectsBytes;
1698 ProxyService service(config_service, resolver, NULL);
1700 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1701 service.SetProxyScriptFetchers(fetcher,
1702 new DoNothingDhcpProxyScriptFetcher());
1704 // Start 2 requests.
1707 TestCompletionCallback callback1;
1708 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1709 callback1.callback(), NULL, BoundNetLog());
1710 EXPECT_EQ(ERR_IO_PENDING, rv);
1713 TestCompletionCallback callback2;
1714 ProxyService::PacRequest* request2;
1715 rv = service.ResolveProxy(GURL("http://request2"), &info2,
1716 callback2.callback(), &request2, BoundNetLog());
1717 EXPECT_EQ(ERR_IO_PENDING, rv);
1719 // Check that nothing has been sent to the proxy resolver yet.
1720 ASSERT_EQ(0u, resolver->pending_requests().size());
1722 // It should be trying to auto-detect first -- FAIL the autodetect during
1723 // the script download.
1724 EXPECT_TRUE(fetcher->has_pending_request());
1725 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1726 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
1728 // Next it should be trying the custom PAC url.
1729 EXPECT_TRUE(fetcher->has_pending_request());
1730 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1731 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1733 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1734 resolver->pending_set_pac_script_request()->script_data()->utf16());
1735 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1737 // Now finally, the pending requests should have been sent to the resolver
1738 // (which was initialized with custom PAC script).
1740 ASSERT_EQ(2u, resolver->pending_requests().size());
1741 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1742 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1744 // Complete the pending requests.
1745 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1746 resolver->pending_requests()[1]->CompleteNow(OK);
1747 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1748 resolver->pending_requests()[0]->CompleteNow(OK);
1750 // Verify that requests ran as expected.
1751 EXPECT_EQ(OK, callback1.WaitForResult());
1752 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1753 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1754 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1755 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
1757 EXPECT_EQ(OK, callback2.WaitForResult());
1758 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1759 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
1760 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
1761 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
1764 // This is the same test as FallbackFromAutodetectToCustomPac, except
1765 // the auto-detect script fails parsing rather than downloading.
1766 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
1768 config.set_auto_detect(true);
1769 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1770 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1772 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1773 MockAsyncProxyResolverExpectsBytes* resolver =
1774 new MockAsyncProxyResolverExpectsBytes;
1775 ProxyService service(config_service, resolver, NULL);
1777 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1778 service.SetProxyScriptFetchers(fetcher,
1779 new DoNothingDhcpProxyScriptFetcher());
1781 // Start 2 requests.
1784 TestCompletionCallback callback1;
1785 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1786 callback1.callback(), NULL, BoundNetLog());
1787 EXPECT_EQ(ERR_IO_PENDING, rv);
1790 TestCompletionCallback callback2;
1791 ProxyService::PacRequest* request2;
1792 rv = service.ResolveProxy(GURL("http://request2"), &info2,
1793 callback2.callback(), &request2, BoundNetLog());
1794 EXPECT_EQ(ERR_IO_PENDING, rv);
1796 // Check that nothing has been sent to the proxy resolver yet.
1797 ASSERT_EQ(0u, resolver->pending_requests().size());
1799 // It should be trying to auto-detect first -- succeed the download.
1800 EXPECT_TRUE(fetcher->has_pending_request());
1801 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1802 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
1804 // The script contents passed failed basic verification step (since didn't
1805 // contain token FindProxyForURL), so it was never passed to the resolver.
1807 // Next it should be trying the custom PAC url.
1808 EXPECT_TRUE(fetcher->has_pending_request());
1809 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1810 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1812 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1813 resolver->pending_set_pac_script_request()->script_data()->utf16());
1814 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1816 // Now finally, the pending requests should have been sent to the resolver
1817 // (which was initialized with custom PAC script).
1819 ASSERT_EQ(2u, resolver->pending_requests().size());
1820 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1821 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1823 // Complete the pending requests.
1824 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1825 resolver->pending_requests()[1]->CompleteNow(OK);
1826 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1827 resolver->pending_requests()[0]->CompleteNow(OK);
1829 // Verify that requests ran as expected.
1830 EXPECT_EQ(OK, callback1.WaitForResult());
1831 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1833 EXPECT_EQ(OK, callback2.WaitForResult());
1834 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1837 // Test that if all of auto-detect, a custom PAC script, and manual settings
1838 // are given, then we will try them in that order.
1839 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
1841 config.set_auto_detect(true);
1842 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1843 config.proxy_rules().ParseFromString("http=foopy:80");
1845 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1846 MockAsyncProxyResolverExpectsBytes* resolver =
1847 new MockAsyncProxyResolverExpectsBytes;
1848 ProxyService service(config_service, resolver, NULL);
1850 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1851 service.SetProxyScriptFetchers(fetcher,
1852 new DoNothingDhcpProxyScriptFetcher());
1854 // Start 2 requests.
1857 TestCompletionCallback callback1;
1858 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1859 callback1.callback(), NULL, BoundNetLog());
1860 EXPECT_EQ(ERR_IO_PENDING, rv);
1863 TestCompletionCallback callback2;
1864 ProxyService::PacRequest* request2;
1865 rv = service.ResolveProxy(GURL("http://request2"), &info2,
1866 callback2.callback(), &request2, BoundNetLog());
1867 EXPECT_EQ(ERR_IO_PENDING, rv);
1869 // Check that nothing has been sent to the proxy resolver yet.
1870 ASSERT_EQ(0u, resolver->pending_requests().size());
1872 // It should be trying to auto-detect first -- fail the download.
1873 EXPECT_TRUE(fetcher->has_pending_request());
1874 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1875 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
1877 // Next it should be trying the custom PAC url -- fail the download.
1878 EXPECT_TRUE(fetcher->has_pending_request());
1879 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1880 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
1882 // Since we never managed to initialize a ProxyResolver, nothing should have
1884 ASSERT_EQ(0u, resolver->pending_requests().size());
1886 // Verify that requests ran as expected -- they should have fallen back to
1887 // the manual proxy configuration for HTTP urls.
1888 EXPECT_EQ(OK, callback1.WaitForResult());
1889 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
1891 EXPECT_EQ(OK, callback2.WaitForResult());
1892 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
1895 // Test that the bypass rules are NOT applied when using autodetect.
1896 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
1898 config.set_auto_detect(true);
1899 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1900 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
1901 config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
1903 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1904 MockAsyncProxyResolverExpectsBytes* resolver =
1905 new MockAsyncProxyResolverExpectsBytes;
1906 ProxyService service(config_service, resolver, NULL);
1908 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1909 service.SetProxyScriptFetchers(fetcher,
1910 new DoNothingDhcpProxyScriptFetcher());
1912 // Start 1 requests.
1915 TestCompletionCallback callback1;
1916 int rv = service.ResolveProxy(
1917 GURL("http://www.google.com"), &info1, callback1.callback(), NULL,
1919 EXPECT_EQ(ERR_IO_PENDING, rv);
1921 // Check that nothing has been sent to the proxy resolver yet.
1922 ASSERT_EQ(0u, resolver->pending_requests().size());
1924 // It should be trying to auto-detect first -- succeed the download.
1925 EXPECT_TRUE(fetcher->has_pending_request());
1926 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1927 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1929 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1930 resolver->pending_set_pac_script_request()->script_data()->utf16());
1931 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1933 ASSERT_EQ(1u, resolver->pending_requests().size());
1934 EXPECT_EQ(GURL("http://www.google.com"),
1935 resolver->pending_requests()[0]->url());
1937 // Complete the pending request.
1938 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1939 resolver->pending_requests()[0]->CompleteNow(OK);
1941 // Verify that request ran as expected.
1942 EXPECT_EQ(OK, callback1.WaitForResult());
1943 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1945 // Start another request, it should pickup the bypass item.
1947 TestCompletionCallback callback2;
1948 rv = service.ResolveProxy(GURL("http://www.google.com"), &info2,
1949 callback2.callback(), NULL, BoundNetLog());
1950 EXPECT_EQ(ERR_IO_PENDING, rv);
1952 ASSERT_EQ(1u, resolver->pending_requests().size());
1953 EXPECT_EQ(GURL("http://www.google.com"),
1954 resolver->pending_requests()[0]->url());
1956 // Complete the pending request.
1957 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1958 resolver->pending_requests()[0]->CompleteNow(OK);
1960 EXPECT_EQ(OK, callback2.WaitForResult());
1961 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1964 // Delete the ProxyService while InitProxyResolver has an outstanding
1965 // request to the script fetcher. When run under valgrind, should not
1966 // have any memory errors (used to be that the ProxyScriptFetcher was
1967 // being deleted prior to the InitProxyResolver).
1968 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
1969 ProxyConfig config =
1970 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
1972 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1973 MockAsyncProxyResolverExpectsBytes* resolver =
1974 new MockAsyncProxyResolverExpectsBytes;
1975 ProxyService service(config_service, resolver, NULL);
1977 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1978 service.SetProxyScriptFetchers(fetcher,
1979 new DoNothingDhcpProxyScriptFetcher());
1984 TestCompletionCallback callback1;
1985 int rv = service.ResolveProxy(GURL("http://www.google.com"), &info1,
1986 callback1.callback(), NULL, BoundNetLog());
1987 EXPECT_EQ(ERR_IO_PENDING, rv);
1989 // Check that nothing has been sent to the proxy resolver yet.
1990 ASSERT_EQ(0u, resolver->pending_requests().size());
1992 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
1993 // and be waiting on that to complete.
1994 EXPECT_TRUE(fetcher->has_pending_request());
1995 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1998 // Delete the ProxyService while InitProxyResolver has an outstanding
1999 // request to the proxy resolver. When run under valgrind, should not
2000 // have any memory errors (used to be that the ProxyResolver was
2001 // being deleted prior to the InitProxyResolver).
2002 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
2003 MockProxyConfigService* config_service =
2004 new MockProxyConfigService("http://foopy/proxy.pac");
2006 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
2008 ProxyService service(config_service, resolver, NULL);
2010 GURL url("http://www.google.com/");
2013 TestCompletionCallback callback;
2014 int rv = service.ResolveProxy(
2015 url, &info, callback.callback(), NULL, BoundNetLog());
2016 EXPECT_EQ(ERR_IO_PENDING, rv);
2018 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2019 resolver->pending_set_pac_script_request()->script_data()->url());
2022 TEST_F(ProxyServiceTest, ResetProxyConfigService) {
2023 ProxyConfig config1;
2024 config1.proxy_rules().ParseFromString("foopy1:8080");
2025 config1.set_auto_detect(false);
2026 ProxyService service(
2027 new MockProxyConfigService(config1),
2028 new MockAsyncProxyResolverExpectsBytes, NULL);
2031 TestCompletionCallback callback1;
2032 int rv = service.ResolveProxy(GURL("http://request1"), &info,
2033 callback1.callback(), NULL, BoundNetLog());
2035 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
2037 ProxyConfig config2;
2038 config2.proxy_rules().ParseFromString("foopy2:8080");
2039 config2.set_auto_detect(false);
2040 service.ResetConfigService(new MockProxyConfigService(config2));
2041 TestCompletionCallback callback2;
2042 rv = service.ResolveProxy(GURL("http://request2"), &info,
2043 callback2.callback(), NULL, BoundNetLog());
2045 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
2048 // Test that when going from a configuration that required PAC to one
2049 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2050 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
2051 ProxyConfig config = ProxyConfig::CreateAutoDetect();
2053 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2054 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
2055 ProxyService service(config_service, resolver, NULL);
2060 TestCompletionCallback callback1;
2061 int rv = service.ResolveProxy(GURL("http://www.google.com"), &info1,
2062 callback1.callback(), NULL, BoundNetLog());
2063 EXPECT_EQ(ERR_IO_PENDING, rv);
2065 // Check that nothing has been sent to the proxy resolver yet.
2066 ASSERT_EQ(0u, resolver->pending_requests().size());
2068 // Successfully set the autodetect script.
2069 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT,
2070 resolver->pending_set_pac_script_request()->script_data()->type());
2071 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2073 // Complete the pending request.
2074 ASSERT_EQ(1u, resolver->pending_requests().size());
2075 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2076 resolver->pending_requests()[0]->CompleteNow(OK);
2078 // Verify that request ran as expected.
2079 EXPECT_EQ(OK, callback1.WaitForResult());
2080 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2082 // Force the ProxyService to pull down a new proxy configuration.
2083 // (Even though the configuration isn't old/bad).
2085 // This new configuration no longer has auto_detect set, so
2086 // requests should complete synchronously now as direct-connect.
2087 config_service->SetConfig(ProxyConfig::CreateDirect());
2089 // Start another request -- the effective configuration has changed.
2091 TestCompletionCallback callback2;
2092 rv = service.ResolveProxy(GURL("http://www.google.com"), &info2,
2093 callback2.callback(), NULL, BoundNetLog());
2096 EXPECT_TRUE(info2.is_direct());
2099 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
2100 MockProxyConfigService* config_service =
2101 new MockProxyConfigService("http://foopy/proxy.pac");
2103 MockAsyncProxyResolverExpectsBytes* resolver =
2104 new MockAsyncProxyResolverExpectsBytes;
2106 CapturingNetLog log;
2108 ProxyService service(config_service, resolver, &log);
2110 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2111 service.SetProxyScriptFetchers(fetcher,
2112 new DoNothingDhcpProxyScriptFetcher());
2114 // Disable the "wait after IP address changes" hack, so this unit-test can
2115 // complete quickly.
2116 service.set_stall_proxy_auto_config_delay(base::TimeDelta());
2121 TestCompletionCallback callback1;
2122 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
2123 callback1.callback(), NULL, BoundNetLog());
2124 EXPECT_EQ(ERR_IO_PENDING, rv);
2126 // The first request should have triggered initial download of PAC script.
2127 EXPECT_TRUE(fetcher->has_pending_request());
2128 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2130 // Nothing has been sent to the resolver yet.
2131 EXPECT_TRUE(resolver->pending_requests().empty());
2133 // At this point the ProxyService should be waiting for the
2134 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2135 // PAC script download completion.
2136 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2138 // Now that the PAC script is downloaded, the request will have been sent to
2139 // the proxy resolver.
2140 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2141 resolver->pending_set_pac_script_request()->script_data()->utf16());
2142 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2144 ASSERT_EQ(1u, resolver->pending_requests().size());
2145 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2147 // Complete the pending request.
2148 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2149 resolver->pending_requests()[0]->CompleteNow(OK);
2151 // Wait for completion callback, and verify that the request ran as expected.
2152 EXPECT_EQ(OK, callback1.WaitForResult());
2153 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2155 // Now simluate a change in the network. The ProxyConfigService is still
2156 // going to return the same PAC URL as before, but this URL needs to be
2157 // refetched on the new network.
2158 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2159 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2161 // Start a second request.
2163 TestCompletionCallback callback2;
2164 rv = service.ResolveProxy(GURL("http://request2"), &info2,
2165 callback2.callback(), NULL, BoundNetLog());
2166 EXPECT_EQ(ERR_IO_PENDING, rv);
2168 // This second request should have triggered the re-download of the PAC
2169 // script (since we marked the network as having changed).
2170 EXPECT_TRUE(fetcher->has_pending_request());
2171 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2173 // Nothing has been sent to the resolver yet.
2174 EXPECT_TRUE(resolver->pending_requests().empty());
2176 // Simulate the PAC script fetch as having completed (this time with
2178 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2180 // Now that the PAC script is downloaded, the second request will have been
2181 // sent to the proxy resolver.
2182 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2183 resolver->pending_set_pac_script_request()->script_data()->utf16());
2184 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2186 ASSERT_EQ(1u, resolver->pending_requests().size());
2187 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2189 // Complete the pending second request.
2190 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2191 resolver->pending_requests()[0]->CompleteNow(OK);
2193 // Wait for completion callback, and verify that the request ran as expected.
2194 EXPECT_EQ(OK, callback2.WaitForResult());
2195 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2197 // Check that the expected events were output to the log stream. In particular
2198 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2199 // setup), and NOT a second time when the IP address changed.
2200 CapturingNetLog::CapturedEntryList entries;
2201 log.GetEntries(&entries);
2203 EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
2204 NetLog::TYPE_PROXY_CONFIG_CHANGED));
2205 ASSERT_EQ(9u, entries.size());
2206 for (size_t i = 1; i < entries.size(); ++i)
2207 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
2210 // This test verifies that the PAC script specified by the settings is
2211 // periodically polled for changes. Specifically, if the initial fetch fails due
2212 // to a network error, we will eventually re-configure the service to use the
2213 // script once it becomes available.
2214 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
2215 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2217 ImmediatePollPolicy poll_policy;
2218 ProxyService::set_pac_script_poll_policy(&poll_policy);
2220 MockProxyConfigService* config_service =
2221 new MockProxyConfigService("http://foopy/proxy.pac");
2223 MockAsyncProxyResolverExpectsBytes* resolver =
2224 new MockAsyncProxyResolverExpectsBytes;
2226 ProxyService service(config_service, resolver, NULL);
2228 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2229 service.SetProxyScriptFetchers(fetcher,
2230 new DoNothingDhcpProxyScriptFetcher());
2235 TestCompletionCallback callback1;
2236 int rv = service.ResolveProxy(
2237 GURL("http://request1"), &info1, callback1.callback(),
2238 NULL, BoundNetLog());
2239 EXPECT_EQ(ERR_IO_PENDING, rv);
2241 // The first request should have triggered initial download of PAC script.
2242 EXPECT_TRUE(fetcher->has_pending_request());
2243 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2245 // Nothing has been sent to the resolver yet.
2246 EXPECT_TRUE(resolver->pending_requests().empty());
2248 // At this point the ProxyService should be waiting for the
2249 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2250 // PAC script download completion.
2252 // We simulate a failed download attempt, the proxy service should now
2253 // fall-back to DIRECT connections.
2254 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2256 ASSERT_TRUE(resolver->pending_requests().empty());
2258 // Wait for completion callback, and verify it used DIRECT.
2259 EXPECT_EQ(OK, callback1.WaitForResult());
2260 EXPECT_TRUE(info1.is_direct());
2262 // At this point we have initialized the proxy service using a PAC script,
2263 // however it failed and fell-back to DIRECT.
2265 // A background task to periodically re-check the PAC script for validity will
2266 // have been started. We will now wait for the next download attempt to start.
2268 // Note that we shouldn't have to wait long here, since our test enables a
2269 // special unit-test mode.
2270 fetcher->WaitUntilFetch();
2272 ASSERT_TRUE(resolver->pending_requests().empty());
2274 // Make sure that our background checker is trying to download the expected
2275 // PAC script (same one as before). This time we will simulate a successful
2276 // download of the script.
2277 EXPECT_TRUE(fetcher->has_pending_request());
2278 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2279 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2281 base::MessageLoop::current()->RunUntilIdle();
2283 // Now that the PAC script is downloaded, it should be used to initialize the
2284 // ProxyResolver. Simulate a successful parse.
2285 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2286 resolver->pending_set_pac_script_request()->script_data()->utf16());
2287 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2289 // At this point the ProxyService should have re-configured itself to use the
2290 // PAC script (thereby recovering from the initial fetch failure). We will
2291 // verify that the next Resolve request uses the resolver rather than
2294 // Start a second request.
2296 TestCompletionCallback callback2;
2297 rv = service.ResolveProxy(
2298 GURL("http://request2"), &info2, callback2.callback(), NULL,
2300 EXPECT_EQ(ERR_IO_PENDING, rv);
2302 // Check that it was sent to the resolver.
2303 ASSERT_EQ(1u, resolver->pending_requests().size());
2304 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2306 // Complete the pending second request.
2307 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2308 resolver->pending_requests()[0]->CompleteNow(OK);
2310 // Wait for completion callback, and verify that the request ran as expected.
2311 EXPECT_EQ(OK, callback2.WaitForResult());
2312 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2315 // This test verifies that the PAC script specified by the settings is
2316 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2317 // however at a later time its *contents* change, we will eventually
2318 // re-configure the service to use the new script.
2319 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
2320 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2322 ImmediatePollPolicy poll_policy;
2323 ProxyService::set_pac_script_poll_policy(&poll_policy);
2325 MockProxyConfigService* config_service =
2326 new MockProxyConfigService("http://foopy/proxy.pac");
2328 MockAsyncProxyResolverExpectsBytes* resolver =
2329 new MockAsyncProxyResolverExpectsBytes;
2331 ProxyService service(config_service, resolver, NULL);
2333 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2334 service.SetProxyScriptFetchers(fetcher,
2335 new DoNothingDhcpProxyScriptFetcher());
2340 TestCompletionCallback callback1;
2341 int rv = service.ResolveProxy(
2342 GURL("http://request1"), &info1, callback1.callback(), NULL,
2344 EXPECT_EQ(ERR_IO_PENDING, rv);
2346 // The first request should have triggered initial download of PAC script.
2347 EXPECT_TRUE(fetcher->has_pending_request());
2348 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2350 // Nothing has been sent to the resolver yet.
2351 EXPECT_TRUE(resolver->pending_requests().empty());
2353 // At this point the ProxyService should be waiting for the
2354 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2355 // PAC script download completion.
2356 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2358 // Now that the PAC script is downloaded, the request will have been sent to
2359 // the proxy resolver.
2360 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2361 resolver->pending_set_pac_script_request()->script_data()->utf16());
2362 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2364 ASSERT_EQ(1u, resolver->pending_requests().size());
2365 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2367 // Complete the pending request.
2368 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2369 resolver->pending_requests()[0]->CompleteNow(OK);
2371 // Wait for completion callback, and verify that the request ran as expected.
2372 EXPECT_EQ(OK, callback1.WaitForResult());
2373 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2375 // At this point we have initialized the proxy service using a PAC script.
2377 // A background task to periodically re-check the PAC script for validity will
2378 // have been started. We will now wait for the next download attempt to start.
2380 // Note that we shouldn't have to wait long here, since our test enables a
2381 // special unit-test mode.
2382 fetcher->WaitUntilFetch();
2384 ASSERT_TRUE(resolver->pending_requests().empty());
2386 // Make sure that our background checker is trying to download the expected
2387 // PAC script (same one as before). This time we will simulate a successful
2388 // download of a DIFFERENT script.
2389 EXPECT_TRUE(fetcher->has_pending_request());
2390 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2391 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2393 base::MessageLoop::current()->RunUntilIdle();
2395 // Now that the PAC script is downloaded, it should be used to initialize the
2396 // ProxyResolver. Simulate a successful parse.
2397 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2398 resolver->pending_set_pac_script_request()->script_data()->utf16());
2399 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2401 // At this point the ProxyService should have re-configured itself to use the
2404 // Start a second request.
2406 TestCompletionCallback callback2;
2407 rv = service.ResolveProxy(
2408 GURL("http://request2"), &info2, callback2.callback(), NULL,
2410 EXPECT_EQ(ERR_IO_PENDING, rv);
2412 // Check that it was sent to the resolver.
2413 ASSERT_EQ(1u, resolver->pending_requests().size());
2414 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2416 // Complete the pending second request.
2417 resolver->pending_requests()[0]->results()->UseNamedProxy("request2: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, callback2.WaitForResult());
2422 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2425 // This test verifies that the PAC script specified by the settings is
2426 // periodically polled for changes. Specifically, if the initial fetch succeeds
2427 // and so does the next poll, however the contents of the downloaded script
2428 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2429 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
2430 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2432 ImmediatePollPolicy poll_policy;
2433 ProxyService::set_pac_script_poll_policy(&poll_policy);
2435 MockProxyConfigService* config_service =
2436 new MockProxyConfigService("http://foopy/proxy.pac");
2438 MockAsyncProxyResolverExpectsBytes* resolver =
2439 new MockAsyncProxyResolverExpectsBytes;
2441 ProxyService service(config_service, resolver, NULL);
2443 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2444 service.SetProxyScriptFetchers(fetcher,
2445 new DoNothingDhcpProxyScriptFetcher());
2450 TestCompletionCallback callback1;
2451 int rv = service.ResolveProxy(
2452 GURL("http://request1"), &info1, callback1.callback(), NULL,
2454 EXPECT_EQ(ERR_IO_PENDING, rv);
2456 // The first request should have triggered initial download of PAC script.
2457 EXPECT_TRUE(fetcher->has_pending_request());
2458 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2460 // Nothing has been sent to the resolver yet.
2461 EXPECT_TRUE(resolver->pending_requests().empty());
2463 // At this point the ProxyService should be waiting for the
2464 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2465 // PAC script download completion.
2466 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2468 // Now that the PAC script is downloaded, the request will have been sent to
2469 // the proxy resolver.
2470 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2471 resolver->pending_set_pac_script_request()->script_data()->utf16());
2472 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2474 ASSERT_EQ(1u, resolver->pending_requests().size());
2475 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2477 // Complete the pending request.
2478 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2479 resolver->pending_requests()[0]->CompleteNow(OK);
2481 // Wait for completion callback, and verify that the request ran as expected.
2482 EXPECT_EQ(OK, callback1.WaitForResult());
2483 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2485 // At this point we have initialized the proxy service using a PAC script.
2487 // A background task to periodically re-check the PAC script for validity will
2488 // have been started. We will now wait for the next download attempt to start.
2490 // Note that we shouldn't have to wait long here, since our test enables a
2491 // special unit-test mode.
2492 fetcher->WaitUntilFetch();
2494 ASSERT_TRUE(resolver->pending_requests().empty());
2496 // Make sure that our background checker is trying to download the expected
2497 // PAC script (same one as before). We will simulate the same response as
2498 // last time (i.e. the script is unchanged).
2499 EXPECT_TRUE(fetcher->has_pending_request());
2500 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2501 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2503 base::MessageLoop::current()->RunUntilIdle();
2505 ASSERT_FALSE(resolver->has_pending_set_pac_script_request());
2507 // At this point the ProxyService is still running the same PAC script as
2510 // Start a second request.
2512 TestCompletionCallback callback2;
2513 rv = service.ResolveProxy(
2514 GURL("http://request2"), &info2, callback2.callback(), NULL,
2516 EXPECT_EQ(ERR_IO_PENDING, rv);
2518 // Check that it was sent to the resolver.
2519 ASSERT_EQ(1u, resolver->pending_requests().size());
2520 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2522 // Complete the pending second request.
2523 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2524 resolver->pending_requests()[0]->CompleteNow(OK);
2526 // Wait for completion callback, and verify that the request ran as expected.
2527 EXPECT_EQ(OK, callback2.WaitForResult());
2528 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2531 // This test verifies that the PAC script specified by the settings is
2532 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2533 // however at a later time it starts to fail, we should re-configure the
2534 // ProxyService to stop using that PAC script.
2535 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
2536 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2538 ImmediatePollPolicy poll_policy;
2539 ProxyService::set_pac_script_poll_policy(&poll_policy);
2541 MockProxyConfigService* config_service =
2542 new MockProxyConfigService("http://foopy/proxy.pac");
2544 MockAsyncProxyResolverExpectsBytes* resolver =
2545 new MockAsyncProxyResolverExpectsBytes;
2547 ProxyService service(config_service, resolver, NULL);
2549 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2550 service.SetProxyScriptFetchers(fetcher,
2551 new DoNothingDhcpProxyScriptFetcher());
2556 TestCompletionCallback callback1;
2557 int rv = service.ResolveProxy(
2558 GURL("http://request1"), &info1, callback1.callback(), NULL,
2560 EXPECT_EQ(ERR_IO_PENDING, rv);
2562 // The first request should have triggered initial download of PAC script.
2563 EXPECT_TRUE(fetcher->has_pending_request());
2564 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2566 // Nothing has been sent to the resolver yet.
2567 EXPECT_TRUE(resolver->pending_requests().empty());
2569 // At this point the ProxyService should be waiting for the
2570 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2571 // PAC script download completion.
2572 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2574 // Now that the PAC script is downloaded, the request will have been sent to
2575 // the proxy resolver.
2576 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2577 resolver->pending_set_pac_script_request()->script_data()->utf16());
2578 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2580 ASSERT_EQ(1u, resolver->pending_requests().size());
2581 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2583 // Complete the pending request.
2584 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2585 resolver->pending_requests()[0]->CompleteNow(OK);
2587 // Wait for completion callback, and verify that the request ran as expected.
2588 EXPECT_EQ(OK, callback1.WaitForResult());
2589 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2591 // At this point we have initialized the proxy service using a PAC script.
2593 // A background task to periodically re-check the PAC script for validity will
2594 // have been started. We will now wait for the next download attempt to start.
2596 // Note that we shouldn't have to wait long here, since our test enables a
2597 // special unit-test mode.
2598 fetcher->WaitUntilFetch();
2600 ASSERT_TRUE(resolver->pending_requests().empty());
2602 // Make sure that our background checker is trying to download the expected
2603 // PAC script (same one as before). This time we will simulate a failure
2604 // to download the script.
2605 EXPECT_TRUE(fetcher->has_pending_request());
2606 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2607 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2609 base::MessageLoop::current()->RunUntilIdle();
2611 // At this point the ProxyService should have re-configured itself to use
2612 // DIRECT connections rather than the given proxy resolver.
2614 // Start a second request.
2616 TestCompletionCallback callback2;
2617 rv = service.ResolveProxy(
2618 GURL("http://request2"), &info2, callback2.callback(), NULL,
2621 EXPECT_TRUE(info2.is_direct());
2624 // Tests that the code which decides at what times to poll the PAC
2625 // script follows the expected policy.
2626 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) {
2627 // Retrieve the internal polling policy implementation used by ProxyService.
2628 scoped_ptr<ProxyService::PacPollPolicy> policy =
2629 ProxyService::CreateDefaultPacPollPolicy();
2632 ProxyService::PacPollPolicy::Mode mode;
2633 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1);
2634 base::TimeDelta delay = initial_delay;
2636 // --------------------------------------------------
2637 // Test the poll sequence in response to a failure.
2638 // --------------------------------------------------
2639 error = ERR_NAME_NOT_RESOLVED;
2642 mode = policy->GetNextDelay(error, initial_delay, &delay);
2643 EXPECT_EQ(8, delay.InSeconds());
2644 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
2647 mode = policy->GetNextDelay(error, delay, &delay);
2648 EXPECT_EQ(32, delay.InSeconds());
2649 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2652 mode = policy->GetNextDelay(error, delay, &delay);
2653 EXPECT_EQ(120, delay.InSeconds());
2654 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2657 mode = policy->GetNextDelay(error, delay, &delay);
2658 EXPECT_EQ(14400, delay.InSeconds());
2659 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2662 mode = policy->GetNextDelay(error, delay, &delay);
2663 EXPECT_EQ(14400, delay.InSeconds());
2664 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2666 // --------------------------------------------------
2667 // Test the poll sequence in response to a success.
2668 // --------------------------------------------------
2672 mode = policy->GetNextDelay(error, initial_delay, &delay);
2673 EXPECT_EQ(43200, delay.InSeconds());
2674 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2677 mode = policy->GetNextDelay(error, delay, &delay);
2678 EXPECT_EQ(43200, delay.InSeconds());
2679 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2682 mode = policy->GetNextDelay(error, delay, &delay);
2683 EXPECT_EQ(43200, delay.InSeconds());
2684 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2687 // This tests the polling of the PAC script. Specifically, it tests that
2688 // polling occurs in response to user activity.
2689 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
2690 ImmediateAfterActivityPollPolicy poll_policy;
2691 ProxyService::set_pac_script_poll_policy(&poll_policy);
2693 MockProxyConfigService* config_service =
2694 new MockProxyConfigService("http://foopy/proxy.pac");
2696 MockAsyncProxyResolverExpectsBytes* resolver =
2697 new MockAsyncProxyResolverExpectsBytes;
2699 ProxyService service(config_service, resolver, NULL);
2701 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2702 service.SetProxyScriptFetchers(fetcher,
2703 new DoNothingDhcpProxyScriptFetcher());
2708 TestCompletionCallback callback1;
2709 int rv = service.ResolveProxy(
2710 GURL("http://request1"), &info1, callback1.callback(), NULL,
2712 EXPECT_EQ(ERR_IO_PENDING, rv);
2714 // The first request should have triggered initial download of PAC script.
2715 EXPECT_TRUE(fetcher->has_pending_request());
2716 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2718 // Nothing has been sent to the resolver yet.
2719 EXPECT_TRUE(resolver->pending_requests().empty());
2721 // At this point the ProxyService should be waiting for the
2722 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2723 // PAC script download completion.
2724 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2726 // Now that the PAC script is downloaded, the request will have been sent to
2727 // the proxy resolver.
2728 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2729 resolver->pending_set_pac_script_request()->script_data()->utf16());
2730 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2732 ASSERT_EQ(1u, resolver->pending_requests().size());
2733 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2735 // Complete the pending request.
2736 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2737 resolver->pending_requests()[0]->CompleteNow(OK);
2739 // Wait for completion callback, and verify that the request ran as expected.
2740 EXPECT_EQ(OK, callback1.WaitForResult());
2741 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2743 // At this point we have initialized the proxy service using a PAC script.
2744 // Our PAC poller is set to update ONLY in response to network activity,
2745 // (i.e. another call to ResolveProxy()).
2747 ASSERT_FALSE(fetcher->has_pending_request());
2748 ASSERT_TRUE(resolver->pending_requests().empty());
2750 // Start a second request.
2752 TestCompletionCallback callback2;
2753 rv = service.ResolveProxy(
2754 GURL("http://request2"), &info2, callback2.callback(), NULL,
2756 EXPECT_EQ(ERR_IO_PENDING, rv);
2758 // This request should have sent work to the resolver; complete it.
2759 ASSERT_EQ(1u, resolver->pending_requests().size());
2760 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2761 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2762 resolver->pending_requests()[0]->CompleteNow(OK);
2764 EXPECT_EQ(OK, callback2.WaitForResult());
2765 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2767 // In response to getting that resolve request, the poller should have
2768 // started the next poll, and made it as far as to request the download.
2770 EXPECT_TRUE(fetcher->has_pending_request());
2771 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2773 // This time we will fail the download, to simulate a PAC script change.
2774 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2776 // Drain the message loop, so ProxyService is notified of the change
2777 // and has a chance to re-configure itself.
2778 base::MessageLoop::current()->RunUntilIdle();
2780 // Start a third request -- this time we expect to get a direct connection
2781 // since the PAC script poller experienced a failure.
2783 TestCompletionCallback callback3;
2784 rv = service.ResolveProxy(
2785 GURL("http://request3"), &info3, callback3.callback(), NULL,
2788 EXPECT_TRUE(info3.is_direct());