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/string_util.h"
12 #include "base/utf_string_conversions.h"
13 #include "googleurl/src/gurl.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/net_log.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/proxy/dhcp_proxy_script_fetcher.h"
19 #include "net/proxy/mock_proxy_resolver.h"
20 #include "net/proxy/mock_proxy_script_fetcher.h"
21 #include "net/proxy/proxy_config_service.h"
22 #include "net/proxy/proxy_resolver.h"
23 #include "net/proxy/proxy_script_fetcher.h"
24 #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());
173 // Check the NetLog was filled correctly.
174 CapturingNetLog::CapturedEntryList entries
;
175 log
.GetEntries(&entries
);
177 EXPECT_EQ(3u, entries
.size());
178 EXPECT_TRUE(LogContainsBeginEvent(
179 entries
, 0, NetLog::TYPE_PROXY_SERVICE
));
180 EXPECT_TRUE(LogContainsEvent(
181 entries
, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST
,
182 NetLog::PHASE_NONE
));
183 EXPECT_TRUE(LogContainsEndEvent(
184 entries
, 2, NetLog::TYPE_PROXY_SERVICE
));
187 TEST_F(ProxyServiceTest
, PAC
) {
188 MockProxyConfigService
* config_service
=
189 new MockProxyConfigService("http://foopy/proxy.pac");
191 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
193 ProxyService
service(config_service
, resolver
, NULL
);
195 GURL
url("http://www.google.com/");
198 TestCompletionCallback callback
;
199 CapturingBoundNetLog log
;
201 int rv
= service
.ResolveProxy(
202 url
, &info
, callback
.callback(), NULL
, log
.bound());
203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
205 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
206 resolver
->pending_set_pac_script_request()->script_data()->url());
207 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
209 ASSERT_EQ(1u, resolver
->pending_requests().size());
210 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
212 // Set the result in proxy resolver.
213 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy");
214 resolver
->pending_requests()[0]->CompleteNow(OK
);
216 EXPECT_EQ(OK
, callback
.WaitForResult());
217 EXPECT_FALSE(info
.is_direct());
218 EXPECT_EQ("foopy:80", info
.proxy_server().ToURI());
219 EXPECT_TRUE(info
.did_use_pac_script());
221 // Check the NetLog was filled correctly.
222 CapturingNetLog::CapturedEntryList entries
;
223 log
.GetEntries(&entries
);
225 EXPECT_EQ(5u, entries
.size());
226 EXPECT_TRUE(LogContainsBeginEvent(
227 entries
, 0, NetLog::TYPE_PROXY_SERVICE
));
228 EXPECT_TRUE(LogContainsBeginEvent(
229 entries
, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
230 EXPECT_TRUE(LogContainsEndEvent(
231 entries
, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
232 EXPECT_TRUE(LogContainsEndEvent(
233 entries
, 4, NetLog::TYPE_PROXY_SERVICE
));
236 // Test that the proxy resolver does not see the URL's username/password
237 // or its reference section.
238 TEST_F(ProxyServiceTest
, PAC_NoIdentityOrHash
) {
239 MockProxyConfigService
* config_service
=
240 new MockProxyConfigService("http://foopy/proxy.pac");
242 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
244 ProxyService
service(config_service
, resolver
, NULL
);
246 GURL
url("http://username:password@www.google.com/?ref#hash#hash");
249 TestCompletionCallback callback
;
250 int rv
= service
.ResolveProxy(
251 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
252 EXPECT_EQ(ERR_IO_PENDING
, rv
);
254 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
255 resolver
->pending_set_pac_script_request()->script_data()->url());
256 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
258 ASSERT_EQ(1u, resolver
->pending_requests().size());
259 // The URL should have been simplified, stripping the username/password/hash.
260 EXPECT_EQ(GURL("http://www.google.com/?ref"),
261 resolver
->pending_requests()[0]->url());
263 // We end here without ever completing the request -- destruction of
264 // ProxyService will cancel the outstanding request.
267 TEST_F(ProxyServiceTest
, PAC_FailoverWithoutDirect
) {
268 MockProxyConfigService
* config_service
=
269 new MockProxyConfigService("http://foopy/proxy.pac");
270 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
272 ProxyService
service(config_service
, resolver
, NULL
);
274 GURL
url("http://www.google.com/");
277 TestCompletionCallback callback1
;
278 int rv
= service
.ResolveProxy(
279 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
280 EXPECT_EQ(ERR_IO_PENDING
, rv
);
282 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
283 resolver
->pending_set_pac_script_request()->script_data()->url());
284 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
286 ASSERT_EQ(1u, resolver
->pending_requests().size());
287 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
289 // Set the result in proxy resolver.
290 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
291 resolver
->pending_requests()[0]->CompleteNow(OK
);
293 EXPECT_EQ(OK
, callback1
.WaitForResult());
294 EXPECT_FALSE(info
.is_direct());
295 EXPECT_EQ("foopy:8080", info
.proxy_server().ToURI());
296 EXPECT_TRUE(info
.did_use_pac_script());
298 // Now, imagine that connecting to foopy:8080 fails: there is nothing
299 // left to fallback to, since our proxy list was NOT terminated by
301 TestCompletionCallback callback2
;
302 rv
= service
.ReconsiderProxyAfterError(
303 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
304 // ReconsiderProxyAfterError returns error indicating nothing left.
305 EXPECT_EQ(ERR_FAILED
, rv
);
306 EXPECT_TRUE(info
.is_empty());
309 // Test that if the execution of the PAC script fails (i.e. javascript runtime
310 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
311 TEST_F(ProxyServiceTest
, PAC_RuntimeError
) {
312 MockProxyConfigService
* config_service
=
313 new MockProxyConfigService("http://foopy/proxy.pac");
314 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
316 ProxyService
service(config_service
, resolver
, NULL
);
318 GURL
url("http://this-causes-js-error/");
321 TestCompletionCallback callback1
;
322 int rv
= service
.ResolveProxy(
323 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
324 EXPECT_EQ(ERR_IO_PENDING
, rv
);
326 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
327 resolver
->pending_set_pac_script_request()->script_data()->url());
328 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
330 ASSERT_EQ(1u, resolver
->pending_requests().size());
331 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
333 // Simulate a failure in the PAC executor.
334 resolver
->pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED
);
336 EXPECT_EQ(OK
, callback1
.WaitForResult());
338 // Since the PAC script was non-mandatory, we should have fallen-back to
340 EXPECT_TRUE(info
.is_direct());
341 EXPECT_TRUE(info
.did_use_pac_script());
342 EXPECT_EQ(1, info
.config_id());
345 // The proxy list could potentially contain the DIRECT fallback choice
346 // in a location other than the very end of the list, and could even
347 // specify it multiple times.
349 // This is not a typical usage, but we will obey it.
350 // (If we wanted to disallow this type of input, the right place to
351 // enforce it would be in parsing the PAC result string).
353 // This test will use the PAC result string:
355 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
357 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
358 // then foobar:20, and then give up and error.
360 // The important check of this test is to make sure that DIRECT is not somehow
361 // cached as being a bad proxy.
362 TEST_F(ProxyServiceTest
, PAC_FailoverAfterDirect
) {
363 MockProxyConfigService
* config_service
=
364 new MockProxyConfigService("http://foopy/proxy.pac");
365 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
367 ProxyService
service(config_service
, resolver
, NULL
);
369 GURL
url("http://www.google.com/");
372 TestCompletionCallback callback1
;
373 int rv
= service
.ResolveProxy(
374 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
375 EXPECT_EQ(ERR_IO_PENDING
, rv
);
377 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
378 resolver
->pending_set_pac_script_request()->script_data()->url());
379 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
381 ASSERT_EQ(1u, resolver
->pending_requests().size());
382 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
384 // Set the result in proxy resolver.
385 resolver
->pending_requests()[0]->results()->UsePacString(
386 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
387 resolver
->pending_requests()[0]->CompleteNow(OK
);
389 EXPECT_EQ(OK
, callback1
.WaitForResult());
390 EXPECT_TRUE(info
.is_direct());
393 TestCompletionCallback callback2
;
394 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
397 EXPECT_FALSE(info
.is_direct());
398 EXPECT_EQ("foobar:10", info
.proxy_server().ToURI());
401 TestCompletionCallback callback3
;
402 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback3
.callback(), NULL
,
405 EXPECT_TRUE(info
.is_direct());
408 TestCompletionCallback callback4
;
409 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
412 EXPECT_FALSE(info
.is_direct());
413 EXPECT_EQ("foobar:20", info
.proxy_server().ToURI());
415 // Fallback 4 -- Nothing to fall back to!
416 TestCompletionCallback callback5
;
417 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback5
.callback(), NULL
,
419 EXPECT_EQ(ERR_FAILED
, rv
);
420 EXPECT_TRUE(info
.is_empty());
423 TEST_F(ProxyServiceTest
, PAC_ConfigSourcePropagates
) {
424 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
425 // to ProxyInfo after the proxy is resolved via a PAC script.
427 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
428 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
430 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
431 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
432 ProxyService
service(config_service
, resolver
, NULL
);
434 // Resolve something.
435 GURL
url("http://www.google.com/");
437 TestCompletionCallback callback
;
438 int rv
= service
.ResolveProxy(
439 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
440 ASSERT_EQ(ERR_IO_PENDING
, rv
);
441 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
442 ASSERT_EQ(1u, resolver
->pending_requests().size());
444 // Set the result in proxy resolver.
445 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy");
446 resolver
->pending_requests()[0]->CompleteNow(OK
);
448 EXPECT_EQ(OK
, callback
.WaitForResult());
449 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
450 EXPECT_TRUE(info
.did_use_pac_script());
453 TEST_F(ProxyServiceTest
, ProxyResolverFails
) {
454 // Test what happens when the ProxyResolver fails. The download and setting
455 // of the PAC script have already succeeded, so this corresponds with a
456 // javascript runtime error while calling FindProxyForURL().
458 MockProxyConfigService
* config_service
=
459 new MockProxyConfigService("http://foopy/proxy.pac");
461 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
463 ProxyService
service(config_service
, resolver
, NULL
);
465 // Start first resolve request.
466 GURL
url("http://www.google.com/");
468 TestCompletionCallback callback1
;
469 int rv
= service
.ResolveProxy(
470 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
471 EXPECT_EQ(ERR_IO_PENDING
, rv
);
473 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
474 resolver
->pending_set_pac_script_request()->script_data()->url());
475 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
477 ASSERT_EQ(1u, resolver
->pending_requests().size());
478 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
480 // Fail the first resolve request in MockAsyncProxyResolver.
481 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
483 // Although the proxy resolver failed the request, ProxyService implicitly
484 // falls-back to DIRECT.
485 EXPECT_EQ(OK
, callback1
.WaitForResult());
486 EXPECT_TRUE(info
.is_direct());
488 // The second resolve request will try to run through the proxy resolver,
489 // regardless of whether the first request failed in it.
490 TestCompletionCallback callback2
;
491 rv
= service
.ResolveProxy(
492 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
493 EXPECT_EQ(ERR_IO_PENDING
, rv
);
495 ASSERT_EQ(1u, resolver
->pending_requests().size());
496 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
498 // This time we will have the resolver succeed (perhaps the PAC script has
499 // a dependency on the current time).
500 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
501 resolver
->pending_requests()[0]->CompleteNow(OK
);
503 EXPECT_EQ(OK
, callback2
.WaitForResult());
504 EXPECT_FALSE(info
.is_direct());
505 EXPECT_EQ("foopy_valid:8080", info
.proxy_server().ToURI());
508 TEST_F(ProxyServiceTest
, ProxyScriptFetcherFailsDownloadingMandatoryPac
) {
509 // Test what happens when the ProxyScriptResolver fails to download a
510 // mandatory PAC script.
513 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
514 config
.set_pac_mandatory(true);
516 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
518 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
520 ProxyService
service(config_service
, resolver
, NULL
);
522 // Start first resolve request.
523 GURL
url("http://www.google.com/");
525 TestCompletionCallback callback1
;
526 int rv
= service
.ResolveProxy(
527 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
528 EXPECT_EQ(ERR_IO_PENDING
, rv
);
530 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
531 resolver
->pending_set_pac_script_request()->script_data()->url());
532 resolver
->pending_set_pac_script_request()->CompleteNow(ERR_FAILED
);
534 ASSERT_EQ(0u, resolver
->pending_requests().size());
536 // As the proxy resolver failed the request and is configured for a mandatory
537 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
538 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
539 callback1
.WaitForResult());
540 EXPECT_FALSE(info
.is_direct());
542 // As the proxy resolver failed the request and is configured for a mandatory
543 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
544 TestCompletionCallback callback2
;
545 rv
= service
.ResolveProxy(
546 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
547 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
, rv
);
548 EXPECT_FALSE(info
.is_direct());
551 TEST_F(ProxyServiceTest
, ProxyResolverFailsParsingJavaScriptMandatoryPac
) {
552 // Test what happens when the ProxyResolver fails that is configured to use a
553 // mandatory PAC script. The download of the PAC script has already
554 // succeeded but the PAC script contains no valid javascript.
557 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
558 config
.set_pac_mandatory(true);
560 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
562 MockAsyncProxyResolverExpectsBytes
* resolver
=
563 new MockAsyncProxyResolverExpectsBytes
;
565 ProxyService
service(config_service
, resolver
, NULL
);
567 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
568 DhcpProxyScriptFetcher
* dhcp_fetcher
= new DoNothingDhcpProxyScriptFetcher();
569 service
.SetProxyScriptFetchers(fetcher
, dhcp_fetcher
);
571 // Start resolve request.
572 GURL
url("http://www.google.com/");
574 TestCompletionCallback callback
;
575 int rv
= service
.ResolveProxy(
576 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
577 EXPECT_EQ(ERR_IO_PENDING
, rv
);
579 // Check that nothing has been sent to the proxy resolver yet.
580 ASSERT_EQ(0u, resolver
->pending_requests().size());
582 // Downloading the PAC script succeeds.
583 EXPECT_TRUE(fetcher
->has_pending_request());
584 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
585 fetcher
->NotifyFetchCompletion(OK
, "invalid-script-contents");
587 EXPECT_FALSE(fetcher
->has_pending_request());
588 ASSERT_EQ(0u, resolver
->pending_requests().size());
590 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
591 // mandatory for this configuration, the ProxyService must not implicitly
592 // fall-back to DIRECT.
593 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
594 callback
.WaitForResult());
595 EXPECT_FALSE(info
.is_direct());
598 TEST_F(ProxyServiceTest
, ProxyResolverFailsInJavaScriptMandatoryPac
) {
599 // Test what happens when the ProxyResolver fails that is configured to use a
600 // mandatory PAC script. The download and setting of the PAC script have
601 // already succeeded, so this corresponds with a javascript runtime error
602 // while calling FindProxyForURL().
605 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
606 config
.set_pac_mandatory(true);
608 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
610 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
612 ProxyService
service(config_service
, resolver
, NULL
);
614 // Start first resolve request.
615 GURL
url("http://www.google.com/");
617 TestCompletionCallback callback1
;
618 int rv
= service
.ResolveProxy(
619 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
620 EXPECT_EQ(ERR_IO_PENDING
, rv
);
622 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
623 resolver
->pending_set_pac_script_request()->script_data()->url());
624 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
626 ASSERT_EQ(1u, resolver
->pending_requests().size());
627 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
629 // Fail the first resolve request in MockAsyncProxyResolver.
630 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
632 // As the proxy resolver failed the request and is configured for a mandatory
633 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
634 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
635 callback1
.WaitForResult());
636 EXPECT_FALSE(info
.is_direct());
638 // The second resolve request will try to run through the proxy resolver,
639 // regardless of whether the first request failed in it.
640 TestCompletionCallback callback2
;
641 rv
= service
.ResolveProxy(
642 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
643 EXPECT_EQ(ERR_IO_PENDING
, rv
);
645 ASSERT_EQ(1u, resolver
->pending_requests().size());
646 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
648 // This time we will have the resolver succeed (perhaps the PAC script has
649 // a dependency on the current time).
650 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
651 resolver
->pending_requests()[0]->CompleteNow(OK
);
653 EXPECT_EQ(OK
, callback2
.WaitForResult());
654 EXPECT_FALSE(info
.is_direct());
655 EXPECT_EQ("foopy_valid:8080", info
.proxy_server().ToURI());
658 TEST_F(ProxyServiceTest
, ProxyFallback
) {
659 // Test what happens when we specify multiple proxy servers and some of them
662 MockProxyConfigService
* config_service
=
663 new MockProxyConfigService("http://foopy/proxy.pac");
665 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
667 ProxyService
service(config_service
, resolver
, NULL
);
669 GURL
url("http://www.google.com/");
671 // Get the proxy information.
673 TestCompletionCallback callback1
;
674 int rv
= service
.ResolveProxy(
675 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
676 EXPECT_EQ(ERR_IO_PENDING
, rv
);
678 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
679 resolver
->pending_set_pac_script_request()->script_data()->url());
680 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
682 ASSERT_EQ(1u, resolver
->pending_requests().size());
683 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
685 // Set the result in proxy resolver.
686 resolver
->pending_requests()[0]->results()->UseNamedProxy(
687 "foopy1:8080;foopy2:9090");
688 resolver
->pending_requests()[0]->CompleteNow(OK
);
690 // The first item is valid.
691 EXPECT_EQ(OK
, callback1
.WaitForResult());
692 EXPECT_FALSE(info
.is_direct());
693 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
695 // Fake an error on the proxy.
696 TestCompletionCallback callback2
;
697 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
701 // The second proxy should be specified.
702 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
703 // Report back that the second proxy worked. This will globally mark the
704 // first proxy as bad.
705 service
.ReportSuccess(info
);
707 TestCompletionCallback callback3
;
708 rv
= service
.ResolveProxy(
709 url
, &info
, callback3
.callback(), NULL
, BoundNetLog());
710 EXPECT_EQ(ERR_IO_PENDING
, rv
);
712 ASSERT_EQ(1u, resolver
->pending_requests().size());
713 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
715 // Set the result in proxy resolver -- the second result is already known
716 // to be bad, so we will not try to use it initially.
717 resolver
->pending_requests()[0]->results()->UseNamedProxy(
718 "foopy3:7070;foopy1:8080;foopy2:9090");
719 resolver
->pending_requests()[0]->CompleteNow(OK
);
721 EXPECT_EQ(OK
, callback3
.WaitForResult());
722 EXPECT_FALSE(info
.is_direct());
723 EXPECT_EQ("foopy3:7070", info
.proxy_server().ToURI());
725 // We fake another error. It should now try the third one.
726 TestCompletionCallback callback4
;
727 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
730 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
732 // We fake another error. At this point we have tried all of the
733 // proxy servers we thought were valid; next we try the proxy server
734 // that was in our bad proxies map (foopy1:8080).
735 TestCompletionCallback callback5
;
736 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback5
.callback(), NULL
,
739 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
741 // Fake another error, the last proxy is gone, the list should now be empty,
742 // so there is nothing left to try.
743 TestCompletionCallback callback6
;
744 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback6
.callback(), NULL
,
746 EXPECT_EQ(ERR_FAILED
, rv
);
747 EXPECT_FALSE(info
.is_direct());
748 EXPECT_TRUE(info
.is_empty());
750 // Look up proxies again
751 TestCompletionCallback callback7
;
752 rv
= service
.ResolveProxy(url
, &info
, callback7
.callback(), NULL
,
754 EXPECT_EQ(ERR_IO_PENDING
, rv
);
756 ASSERT_EQ(1u, resolver
->pending_requests().size());
757 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
759 // This time, the first 3 results have been found to be bad, but only the
760 // first proxy has been confirmed ...
761 resolver
->pending_requests()[0]->results()->UseNamedProxy(
762 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
763 resolver
->pending_requests()[0]->CompleteNow(OK
);
765 // ... therefore, we should see the second proxy first.
766 EXPECT_EQ(OK
, callback7
.WaitForResult());
767 EXPECT_FALSE(info
.is_direct());
768 EXPECT_EQ("foopy3:7070", info
.proxy_server().ToURI());
770 // TODO(nsylvain): Test that the proxy can be retried after the delay.
773 // This test is similar to ProxyFallback, but this time we have an explicit
774 // fallback choice to DIRECT.
775 TEST_F(ProxyServiceTest
, ProxyFallbackToDirect
) {
776 MockProxyConfigService
* config_service
=
777 new MockProxyConfigService("http://foopy/proxy.pac");
779 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
781 ProxyService
service(config_service
, resolver
, NULL
);
783 GURL
url("http://www.google.com/");
785 // Get the proxy information.
787 TestCompletionCallback callback1
;
788 int rv
= service
.ResolveProxy(
789 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
790 EXPECT_EQ(ERR_IO_PENDING
, rv
);
792 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
793 resolver
->pending_set_pac_script_request()->script_data()->url());
794 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
796 ASSERT_EQ(1u, resolver
->pending_requests().size());
797 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
799 // Set the result in proxy resolver.
800 resolver
->pending_requests()[0]->results()->UsePacString(
801 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
802 resolver
->pending_requests()[0]->CompleteNow(OK
);
804 // Get the first result.
805 EXPECT_EQ(OK
, callback1
.WaitForResult());
806 EXPECT_FALSE(info
.is_direct());
807 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
809 // Fake an error on the proxy.
810 TestCompletionCallback callback2
;
811 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
815 // Now we get back the second proxy.
816 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
818 // Fake an error on this proxy as well.
819 TestCompletionCallback callback3
;
820 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback3
.callback(), NULL
,
824 // Finally, we get back DIRECT.
825 EXPECT_TRUE(info
.is_direct());
827 // Now we tell the proxy service that even DIRECT failed.
828 TestCompletionCallback callback4
;
829 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
831 // There was nothing left to try after DIRECT, so we are out of
833 EXPECT_EQ(ERR_FAILED
, rv
);
836 TEST_F(ProxyServiceTest
, ProxyFallback_NewSettings
) {
837 // Test proxy failover when new settings are available.
839 MockProxyConfigService
* config_service
=
840 new MockProxyConfigService("http://foopy/proxy.pac");
842 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
844 ProxyService
service(config_service
, resolver
, NULL
);
846 GURL
url("http://www.google.com/");
848 // Get the proxy information.
850 TestCompletionCallback callback1
;
851 int rv
= service
.ResolveProxy(
852 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
853 EXPECT_EQ(ERR_IO_PENDING
, rv
);
855 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
856 resolver
->pending_set_pac_script_request()->script_data()->url());
857 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
859 ASSERT_EQ(1u, resolver
->pending_requests().size());
860 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
862 // Set the result in proxy resolver.
863 resolver
->pending_requests()[0]->results()->UseNamedProxy(
864 "foopy1:8080;foopy2:9090");
865 resolver
->pending_requests()[0]->CompleteNow(OK
);
867 // The first item is valid.
868 EXPECT_EQ(OK
, callback1
.WaitForResult());
869 EXPECT_FALSE(info
.is_direct());
870 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
872 // Fake an error on the proxy, and also a new configuration on the proxy.
873 config_service
->SetConfig(
874 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
876 TestCompletionCallback callback2
;
877 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
881 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
882 resolver
->pending_set_pac_script_request()->script_data()->url());
883 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
885 ASSERT_EQ(1u, resolver
->pending_requests().size());
886 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
888 resolver
->pending_requests()[0]->results()->UseNamedProxy(
889 "foopy1:8080;foopy2:9090");
890 resolver
->pending_requests()[0]->CompleteNow(OK
);
892 // The first proxy is still there since the configuration changed.
893 EXPECT_EQ(OK
, callback2
.WaitForResult());
894 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
896 // We fake another error. It should now ignore the first one.
897 TestCompletionCallback callback3
;
898 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback3
.callback(), NULL
,
901 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
903 // We simulate a new configuration.
904 config_service
->SetConfig(
905 ProxyConfig::CreateFromCustomPacURL(
906 GURL("http://foopy-new2/proxy.pac")));
908 // We fake another error. It should go back to the first proxy.
909 TestCompletionCallback callback4
;
910 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
912 EXPECT_EQ(ERR_IO_PENDING
, rv
);
914 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
915 resolver
->pending_set_pac_script_request()->script_data()->url());
916 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
918 ASSERT_EQ(1u, resolver
->pending_requests().size());
919 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
921 resolver
->pending_requests()[0]->results()->UseNamedProxy(
922 "foopy1:8080;foopy2:9090");
923 resolver
->pending_requests()[0]->CompleteNow(OK
);
925 EXPECT_EQ(OK
, callback4
.WaitForResult());
926 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
929 TEST_F(ProxyServiceTest
, ProxyFallback_BadConfig
) {
930 // Test proxy failover when the configuration is bad.
932 MockProxyConfigService
* config_service
=
933 new MockProxyConfigService("http://foopy/proxy.pac");
935 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
937 ProxyService
service(config_service
, resolver
, NULL
);
939 GURL
url("http://www.google.com/");
941 // Get the proxy information.
943 TestCompletionCallback callback1
;
944 int rv
= service
.ResolveProxy(
945 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
946 EXPECT_EQ(ERR_IO_PENDING
, rv
);
948 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
949 resolver
->pending_set_pac_script_request()->script_data()->url());
950 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
951 ASSERT_EQ(1u, resolver
->pending_requests().size());
952 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
954 resolver
->pending_requests()[0]->results()->UseNamedProxy(
955 "foopy1:8080;foopy2:9090");
956 resolver
->pending_requests()[0]->CompleteNow(OK
);
958 // The first item is valid.
959 EXPECT_EQ(OK
, callback1
.WaitForResult());
960 EXPECT_FALSE(info
.is_direct());
961 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
963 // Fake a proxy error.
964 TestCompletionCallback callback2
;
965 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
969 // The first proxy is ignored, and the second one is selected.
970 EXPECT_FALSE(info
.is_direct());
971 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
973 // Fake a PAC failure.
975 TestCompletionCallback callback3
;
976 rv
= service
.ResolveProxy(
977 url
, &info2
, callback3
.callback(), NULL
, BoundNetLog());
978 EXPECT_EQ(ERR_IO_PENDING
, rv
);
980 ASSERT_EQ(1u, resolver
->pending_requests().size());
981 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
983 // This simulates a javascript runtime error in the PAC script.
984 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
986 // Although the resolver failed, the ProxyService will implicitly fall-back
987 // to a DIRECT connection.
988 EXPECT_EQ(OK
, callback3
.WaitForResult());
989 EXPECT_TRUE(info2
.is_direct());
990 EXPECT_FALSE(info2
.is_empty());
992 // The PAC script will work properly next time and successfully return a
993 // proxy list. Since we have not marked the configuration as bad, it should
994 // "just work" the next time we call it.
996 TestCompletionCallback callback4
;
997 rv
= service
.ReconsiderProxyAfterError(url
, &info3
, callback4
.callback(),
998 NULL
, BoundNetLog());
999 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1001 ASSERT_EQ(1u, resolver
->pending_requests().size());
1002 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1004 resolver
->pending_requests()[0]->results()->UseNamedProxy(
1005 "foopy1:8080;foopy2:9090");
1006 resolver
->pending_requests()[0]->CompleteNow(OK
);
1008 // The first proxy is not there since the it was added to the bad proxies
1009 // list by the earlier ReconsiderProxyAfterError().
1010 EXPECT_EQ(OK
, callback4
.WaitForResult());
1011 EXPECT_FALSE(info3
.is_direct());
1012 EXPECT_EQ("foopy1:8080", info3
.proxy_server().ToURI());
1015 TEST_F(ProxyServiceTest
, ProxyFallback_BadConfigMandatory
) {
1016 // Test proxy failover when the configuration is bad.
1019 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1021 config
.set_pac_mandatory(true);
1022 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1024 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
1026 ProxyService
service(config_service
, resolver
, NULL
);
1028 GURL
url("http://www.google.com/");
1030 // Get the proxy information.
1032 TestCompletionCallback callback1
;
1033 int rv
= service
.ResolveProxy(
1034 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
1035 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1037 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1038 resolver
->pending_set_pac_script_request()->script_data()->url());
1039 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1040 ASSERT_EQ(1u, resolver
->pending_requests().size());
1041 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1043 resolver
->pending_requests()[0]->results()->UseNamedProxy(
1044 "foopy1:8080;foopy2:9090");
1045 resolver
->pending_requests()[0]->CompleteNow(OK
);
1047 // The first item is valid.
1048 EXPECT_EQ(OK
, callback1
.WaitForResult());
1049 EXPECT_FALSE(info
.is_direct());
1050 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1052 // Fake a proxy error.
1053 TestCompletionCallback callback2
;
1054 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
1058 // The first proxy is ignored, and the second one is selected.
1059 EXPECT_FALSE(info
.is_direct());
1060 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
1062 // Fake a PAC failure.
1064 TestCompletionCallback callback3
;
1065 rv
= service
.ResolveProxy(
1066 url
, &info2
, callback3
.callback(), NULL
, BoundNetLog());
1067 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1069 ASSERT_EQ(1u, resolver
->pending_requests().size());
1070 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1072 // This simulates a javascript runtime error in the PAC script.
1073 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
1075 // Although the resolver failed, the ProxyService will NOT fall-back
1076 // to a DIRECT connection as it is configured as mandatory.
1077 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
1078 callback3
.WaitForResult());
1079 EXPECT_FALSE(info2
.is_direct());
1080 EXPECT_TRUE(info2
.is_empty());
1082 // The PAC script will work properly next time and successfully return a
1083 // proxy list. Since we have not marked the configuration as bad, it should
1084 // "just work" the next time we call it.
1086 TestCompletionCallback callback4
;
1087 rv
= service
.ReconsiderProxyAfterError(url
, &info3
, callback4
.callback(),
1088 NULL
, BoundNetLog());
1089 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1091 ASSERT_EQ(1u, resolver
->pending_requests().size());
1092 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1094 resolver
->pending_requests()[0]->results()->UseNamedProxy(
1095 "foopy1:8080;foopy2:9090");
1096 resolver
->pending_requests()[0]->CompleteNow(OK
);
1098 // The first proxy is not there since the it was added to the bad proxies
1099 // list by the earlier ReconsiderProxyAfterError().
1100 EXPECT_EQ(OK
, callback4
.WaitForResult());
1101 EXPECT_FALSE(info3
.is_direct());
1102 EXPECT_EQ("foopy1:8080", info3
.proxy_server().ToURI());
1105 TEST_F(ProxyServiceTest
, ProxyBypassList
) {
1106 // Test that the proxy bypass rules are consulted.
1108 TestCompletionCallback callback
[2];
1111 config
.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1112 config
.set_auto_detect(false);
1113 config
.proxy_rules().bypass_rules
.ParseFromString("*.org");
1115 ProxyService
service(
1116 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1119 GURL
url1("http://www.webkit.org");
1120 GURL
url2("http://www.webkit.com");
1122 // Request for a .org domain should bypass proxy.
1123 rv
= service
.ResolveProxy(
1124 url1
, &info
[0], callback
[0].callback(), NULL
, BoundNetLog());
1126 EXPECT_TRUE(info
[0].is_direct());
1128 // Request for a .com domain hits the proxy.
1129 rv
= service
.ResolveProxy(
1130 url2
, &info
[1], callback
[1].callback(), NULL
, BoundNetLog());
1132 EXPECT_EQ("foopy1:8080", info
[1].proxy_server().ToURI());
1136 TEST_F(ProxyServiceTest
, PerProtocolProxyTests
) {
1138 config
.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1139 config
.set_auto_detect(false);
1141 ProxyService
service(
1142 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1143 GURL
test_url("http://www.msn.com");
1145 TestCompletionCallback callback
;
1146 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1149 EXPECT_FALSE(info
.is_direct());
1150 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1153 ProxyService
service(
1154 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1155 GURL
test_url("ftp://ftp.google.com");
1157 TestCompletionCallback callback
;
1158 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1161 EXPECT_TRUE(info
.is_direct());
1162 EXPECT_EQ("direct://", info
.proxy_server().ToURI());
1165 ProxyService
service(
1166 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1167 GURL
test_url("https://webbranch.techcu.com");
1169 TestCompletionCallback callback
;
1170 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1173 EXPECT_FALSE(info
.is_direct());
1174 EXPECT_EQ("foopy2:8080", info
.proxy_server().ToURI());
1177 config
.proxy_rules().ParseFromString("foopy1:8080");
1178 ProxyService
service(
1179 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1180 GURL
test_url("http://www.microsoft.com");
1182 TestCompletionCallback callback
;
1183 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1186 EXPECT_FALSE(info
.is_direct());
1187 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1191 TEST_F(ProxyServiceTest
, ProxyConfigSourcePropagates
) {
1192 // Test that the proxy config source is set correctly when resolving proxies
1193 // using manual proxy rules. Namely, the config source should only be set if
1194 // any of the rules were applied.
1197 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1198 config
.proxy_rules().ParseFromString("https=foopy2:8080");
1199 ProxyService
service(
1200 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1201 GURL
test_url("http://www.google.com");
1203 TestCompletionCallback callback
;
1204 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1207 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1208 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1212 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1213 config
.proxy_rules().ParseFromString("https=foopy2:8080");
1214 ProxyService
service(
1215 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1216 GURL
test_url("https://www.google.com");
1218 TestCompletionCallback callback
;
1219 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1222 // Used the HTTPS proxy. So source should be TEST.
1223 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1227 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1228 ProxyService
service(
1229 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1230 GURL
test_url("http://www.google.com");
1232 TestCompletionCallback callback
;
1233 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1236 // ProxyConfig is empty. Source should still be TEST.
1237 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1241 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1242 // fall back to the SOCKS proxy.
1243 TEST_F(ProxyServiceTest
, DefaultProxyFallbackToSOCKS
) {
1245 config
.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1246 config
.set_auto_detect(false);
1247 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME
,
1248 config
.proxy_rules().type
);
1251 ProxyService
service(
1252 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1253 GURL
test_url("http://www.msn.com");
1255 TestCompletionCallback callback
;
1256 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1259 EXPECT_FALSE(info
.is_direct());
1260 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1263 ProxyService
service(
1264 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1265 GURL
test_url("ftp://ftp.google.com");
1267 TestCompletionCallback callback
;
1268 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1271 EXPECT_FALSE(info
.is_direct());
1272 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1275 ProxyService
service(
1276 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1277 GURL
test_url("https://webbranch.techcu.com");
1279 TestCompletionCallback callback
;
1280 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1283 EXPECT_FALSE(info
.is_direct());
1284 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1287 ProxyService
service(
1288 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1289 GURL
test_url("unknown://www.microsoft.com");
1291 TestCompletionCallback callback
;
1292 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1295 EXPECT_FALSE(info
.is_direct());
1296 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1300 // Test cancellation of an in-progress request.
1301 TEST_F(ProxyServiceTest
, CancelInProgressRequest
) {
1302 MockProxyConfigService
* config_service
=
1303 new MockProxyConfigService("http://foopy/proxy.pac");
1305 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
1307 ProxyService
service(config_service
, resolver
, NULL
);
1309 // Start 3 requests.
1312 TestCompletionCallback callback1
;
1313 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1314 callback1
.callback(), NULL
, BoundNetLog());
1315 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1317 // Nothing has been sent to the proxy resolver yet, since the proxy
1318 // resolver has not been configured yet.
1319 ASSERT_EQ(0u, resolver
->pending_requests().size());
1321 // Successfully initialize the PAC script.
1322 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1323 resolver
->pending_set_pac_script_request()->script_data()->url());
1324 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1326 ASSERT_EQ(1u, resolver
->pending_requests().size());
1327 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1330 TestCompletionCallback callback2
;
1331 ProxyService::PacRequest
* request2
;
1332 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1333 callback2
.callback(), &request2
, BoundNetLog());
1334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1335 ASSERT_EQ(2u, resolver
->pending_requests().size());
1336 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1339 TestCompletionCallback callback3
;
1340 rv
= service
.ResolveProxy(GURL("http://request3"), &info3
,
1341 callback3
.callback(), NULL
, BoundNetLog());
1342 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1343 ASSERT_EQ(3u, resolver
->pending_requests().size());
1344 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[2]->url());
1346 // Cancel the second request
1347 service
.CancelPacRequest(request2
);
1349 ASSERT_EQ(2u, resolver
->pending_requests().size());
1350 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1351 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[1]->url());
1353 // Complete the two un-cancelled requests.
1354 // We complete the last one first, just to mix it up a bit.
1355 resolver
->pending_requests()[1]->results()->UseNamedProxy("request3:80");
1356 resolver
->pending_requests()[1]->CompleteNow(OK
);
1358 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1359 resolver
->pending_requests()[0]->CompleteNow(OK
);
1361 // Complete and verify that requests ran as expected.
1362 EXPECT_EQ(OK
, callback1
.WaitForResult());
1363 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1365 EXPECT_FALSE(callback2
.have_result()); // Cancelled.
1366 ASSERT_EQ(1u, resolver
->cancelled_requests().size());
1367 EXPECT_EQ(GURL("http://request2"), resolver
->cancelled_requests()[0]->url());
1369 EXPECT_EQ(OK
, callback3
.WaitForResult());
1370 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1373 // Test the initial PAC download for resolver that expects bytes.
1374 TEST_F(ProxyServiceTest
, InitialPACScriptDownload
) {
1375 MockProxyConfigService
* config_service
=
1376 new MockProxyConfigService("http://foopy/proxy.pac");
1378 MockAsyncProxyResolverExpectsBytes
* resolver
=
1379 new MockAsyncProxyResolverExpectsBytes
;
1381 ProxyService
service(config_service
, resolver
, NULL
);
1383 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1384 service
.SetProxyScriptFetchers(fetcher
,
1385 new DoNothingDhcpProxyScriptFetcher());
1387 // Start 3 requests.
1390 TestCompletionCallback callback1
;
1391 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1392 callback1
.callback(), NULL
, BoundNetLog());
1393 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1395 // The first request should have triggered download of PAC script.
1396 EXPECT_TRUE(fetcher
->has_pending_request());
1397 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1400 TestCompletionCallback callback2
;
1401 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1402 callback2
.callback(), NULL
, BoundNetLog());
1403 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1406 TestCompletionCallback callback3
;
1407 rv
= service
.ResolveProxy(GURL("http://request3"), &info3
,
1408 callback3
.callback(), NULL
, BoundNetLog());
1409 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1411 // Nothing has been sent to the resolver yet.
1412 EXPECT_TRUE(resolver
->pending_requests().empty());
1414 // At this point the ProxyService should be waiting for the
1415 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1416 // PAC script download completion.
1417 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1419 // Now that the PAC script is downloaded, it will have been sent to the proxy
1421 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1422 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1423 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1425 ASSERT_EQ(3u, resolver
->pending_requests().size());
1426 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1427 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1428 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[2]->url());
1430 // Complete all the requests (in some order).
1431 // Note that as we complete requests, they shift up in |pending_requests()|.
1433 resolver
->pending_requests()[2]->results()->UseNamedProxy("request3:80");
1434 resolver
->pending_requests()[2]->CompleteNow(OK
);
1436 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1437 resolver
->pending_requests()[0]->CompleteNow(OK
);
1439 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1440 resolver
->pending_requests()[0]->CompleteNow(OK
);
1442 // Complete and verify that requests ran as expected.
1443 EXPECT_EQ(OK
, callback1
.WaitForResult());
1444 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1446 EXPECT_EQ(OK
, callback2
.WaitForResult());
1447 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1449 EXPECT_EQ(OK
, callback3
.WaitForResult());
1450 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1453 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1454 TEST_F(ProxyServiceTest
, ChangeScriptFetcherWhilePACDownloadInProgress
) {
1455 MockProxyConfigService
* config_service
=
1456 new MockProxyConfigService("http://foopy/proxy.pac");
1458 MockAsyncProxyResolverExpectsBytes
* resolver
=
1459 new MockAsyncProxyResolverExpectsBytes
;
1461 ProxyService
service(config_service
, resolver
, NULL
);
1463 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1464 service
.SetProxyScriptFetchers(fetcher
,
1465 new DoNothingDhcpProxyScriptFetcher());
1467 // Start 2 requests.
1470 TestCompletionCallback callback1
;
1471 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1472 callback1
.callback(), NULL
, BoundNetLog());
1473 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1475 // The first request should have triggered download of PAC script.
1476 EXPECT_TRUE(fetcher
->has_pending_request());
1477 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1480 TestCompletionCallback callback2
;
1481 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1482 callback2
.callback(), NULL
, BoundNetLog());
1483 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1485 // At this point the ProxyService should be waiting for the
1486 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1487 // PAC script download completion.
1489 // We now change out the ProxyService's script fetcher. We should restart
1490 // the initialization with the new fetcher.
1492 fetcher
= new MockProxyScriptFetcher
;
1493 service
.SetProxyScriptFetchers(fetcher
,
1494 new DoNothingDhcpProxyScriptFetcher());
1496 // Nothing has been sent to the resolver yet.
1497 EXPECT_TRUE(resolver
->pending_requests().empty());
1499 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1501 // Now that the PAC script is downloaded, it will have been sent to the proxy
1503 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1504 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1505 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1507 ASSERT_EQ(2u, resolver
->pending_requests().size());
1508 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1509 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1512 // Test cancellation of a request, while the PAC script is being fetched.
1513 TEST_F(ProxyServiceTest
, CancelWhilePACFetching
) {
1514 MockProxyConfigService
* config_service
=
1515 new MockProxyConfigService("http://foopy/proxy.pac");
1517 MockAsyncProxyResolverExpectsBytes
* resolver
=
1518 new MockAsyncProxyResolverExpectsBytes
;
1520 ProxyService
service(config_service
, resolver
, NULL
);
1522 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1523 service
.SetProxyScriptFetchers(fetcher
,
1524 new DoNothingDhcpProxyScriptFetcher());
1526 // Start 3 requests.
1528 TestCompletionCallback callback1
;
1529 ProxyService::PacRequest
* request1
;
1530 CapturingBoundNetLog log1
;
1531 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1532 callback1
.callback(), &request1
, log1
.bound());
1533 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1535 // The first request should have triggered download of PAC script.
1536 EXPECT_TRUE(fetcher
->has_pending_request());
1537 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1540 TestCompletionCallback callback2
;
1541 ProxyService::PacRequest
* request2
;
1542 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1543 callback2
.callback(), &request2
, BoundNetLog());
1544 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1547 TestCompletionCallback callback3
;
1548 rv
= service
.ResolveProxy(GURL("http://request3"), &info3
,
1549 callback3
.callback(), NULL
, BoundNetLog());
1550 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1552 // Nothing has been sent to the resolver yet.
1553 EXPECT_TRUE(resolver
->pending_requests().empty());
1555 // Cancel the first 2 requests.
1556 service
.CancelPacRequest(request1
);
1557 service
.CancelPacRequest(request2
);
1559 // At this point the ProxyService should be waiting for the
1560 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1561 // PAC script download completion.
1562 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1564 // Now that the PAC script is downloaded, it will have been sent to the
1566 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1567 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1568 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1570 ASSERT_EQ(1u, resolver
->pending_requests().size());
1571 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[0]->url());
1573 // Complete all the requests.
1574 resolver
->pending_requests()[0]->results()->UseNamedProxy("request3:80");
1575 resolver
->pending_requests()[0]->CompleteNow(OK
);
1577 EXPECT_EQ(OK
, callback3
.WaitForResult());
1578 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1580 EXPECT_TRUE(resolver
->cancelled_requests().empty());
1582 EXPECT_FALSE(callback1
.have_result()); // Cancelled.
1583 EXPECT_FALSE(callback2
.have_result()); // Cancelled.
1585 CapturingNetLog::CapturedEntryList entries1
;
1586 log1
.GetEntries(&entries1
);
1588 // Check the NetLog for request 1 (which was cancelled) got filled properly.
1589 EXPECT_EQ(4u, entries1
.size());
1590 EXPECT_TRUE(LogContainsBeginEvent(
1591 entries1
, 0, NetLog::TYPE_PROXY_SERVICE
));
1592 EXPECT_TRUE(LogContainsBeginEvent(
1593 entries1
, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
1594 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1595 // the cancellation occured.
1596 EXPECT_TRUE(LogContainsEvent(
1597 entries1
, 2, NetLog::TYPE_CANCELLED
, NetLog::PHASE_NONE
));
1598 EXPECT_TRUE(LogContainsEndEvent(
1599 entries1
, 3, NetLog::TYPE_PROXY_SERVICE
));
1602 // Test that if auto-detect fails, we fall-back to the custom pac.
1603 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomPac
) {
1605 config
.set_auto_detect(true);
1606 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1607 config
.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1609 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1610 MockAsyncProxyResolverExpectsBytes
* resolver
=
1611 new MockAsyncProxyResolverExpectsBytes
;
1612 ProxyService
service(config_service
, resolver
, NULL
);
1614 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1615 service
.SetProxyScriptFetchers(fetcher
,
1616 new DoNothingDhcpProxyScriptFetcher());
1618 // Start 2 requests.
1621 TestCompletionCallback callback1
;
1622 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1623 callback1
.callback(), NULL
, BoundNetLog());
1624 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1627 TestCompletionCallback callback2
;
1628 ProxyService::PacRequest
* request2
;
1629 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1630 callback2
.callback(), &request2
, BoundNetLog());
1631 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1633 // Check that nothing has been sent to the proxy resolver yet.
1634 ASSERT_EQ(0u, resolver
->pending_requests().size());
1636 // It should be trying to auto-detect first -- FAIL the autodetect during
1637 // the script download.
1638 EXPECT_TRUE(fetcher
->has_pending_request());
1639 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1640 fetcher
->NotifyFetchCompletion(ERR_FAILED
, "");
1642 // Next it should be trying the custom PAC url.
1643 EXPECT_TRUE(fetcher
->has_pending_request());
1644 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1645 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1647 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1648 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1649 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1651 // Now finally, the pending requests should have been sent to the resolver
1652 // (which was initialized with custom PAC script).
1654 ASSERT_EQ(2u, resolver
->pending_requests().size());
1655 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1656 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1658 // Complete the pending requests.
1659 resolver
->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1660 resolver
->pending_requests()[1]->CompleteNow(OK
);
1661 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1662 resolver
->pending_requests()[0]->CompleteNow(OK
);
1664 // Verify that requests ran as expected.
1665 EXPECT_EQ(OK
, callback1
.WaitForResult());
1666 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1668 EXPECT_EQ(OK
, callback2
.WaitForResult());
1669 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1672 // This is the same test as FallbackFromAutodetectToCustomPac, except
1673 // the auto-detect script fails parsing rather than downloading.
1674 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomPac2
) {
1676 config
.set_auto_detect(true);
1677 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1678 config
.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1680 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1681 MockAsyncProxyResolverExpectsBytes
* resolver
=
1682 new MockAsyncProxyResolverExpectsBytes
;
1683 ProxyService
service(config_service
, resolver
, NULL
);
1685 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1686 service
.SetProxyScriptFetchers(fetcher
,
1687 new DoNothingDhcpProxyScriptFetcher());
1689 // Start 2 requests.
1692 TestCompletionCallback callback1
;
1693 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1694 callback1
.callback(), NULL
, BoundNetLog());
1695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1698 TestCompletionCallback callback2
;
1699 ProxyService::PacRequest
* request2
;
1700 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1701 callback2
.callback(), &request2
, BoundNetLog());
1702 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1704 // Check that nothing has been sent to the proxy resolver yet.
1705 ASSERT_EQ(0u, resolver
->pending_requests().size());
1707 // It should be trying to auto-detect first -- succeed the download.
1708 EXPECT_TRUE(fetcher
->has_pending_request());
1709 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1710 fetcher
->NotifyFetchCompletion(OK
, "invalid-script-contents");
1712 // The script contents passed failed basic verification step (since didn't
1713 // contain token FindProxyForURL), so it was never passed to the resolver.
1715 // Next it should be trying the custom PAC url.
1716 EXPECT_TRUE(fetcher
->has_pending_request());
1717 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1718 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1720 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1721 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1722 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1724 // Now finally, the pending requests should have been sent to the resolver
1725 // (which was initialized with custom PAC script).
1727 ASSERT_EQ(2u, resolver
->pending_requests().size());
1728 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1729 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1731 // Complete the pending requests.
1732 resolver
->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1733 resolver
->pending_requests()[1]->CompleteNow(OK
);
1734 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1735 resolver
->pending_requests()[0]->CompleteNow(OK
);
1737 // Verify that requests ran as expected.
1738 EXPECT_EQ(OK
, callback1
.WaitForResult());
1739 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1741 EXPECT_EQ(OK
, callback2
.WaitForResult());
1742 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1745 // Test that if all of auto-detect, a custom PAC script, and manual settings
1746 // are given, then we will try them in that order.
1747 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomToManual
) {
1749 config
.set_auto_detect(true);
1750 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1751 config
.proxy_rules().ParseFromString("http=foopy:80");
1753 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1754 MockAsyncProxyResolverExpectsBytes
* resolver
=
1755 new MockAsyncProxyResolverExpectsBytes
;
1756 ProxyService
service(config_service
, resolver
, NULL
);
1758 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1759 service
.SetProxyScriptFetchers(fetcher
,
1760 new DoNothingDhcpProxyScriptFetcher());
1762 // Start 2 requests.
1765 TestCompletionCallback callback1
;
1766 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1767 callback1
.callback(), NULL
, BoundNetLog());
1768 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1771 TestCompletionCallback callback2
;
1772 ProxyService::PacRequest
* request2
;
1773 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1774 callback2
.callback(), &request2
, BoundNetLog());
1775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1777 // Check that nothing has been sent to the proxy resolver yet.
1778 ASSERT_EQ(0u, resolver
->pending_requests().size());
1780 // It should be trying to auto-detect first -- fail the download.
1781 EXPECT_TRUE(fetcher
->has_pending_request());
1782 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1783 fetcher
->NotifyFetchCompletion(ERR_FAILED
, "");
1785 // Next it should be trying the custom PAC url -- fail the download.
1786 EXPECT_TRUE(fetcher
->has_pending_request());
1787 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1788 fetcher
->NotifyFetchCompletion(ERR_FAILED
, "");
1790 // Since we never managed to initialize a ProxyResolver, nothing should have
1792 ASSERT_EQ(0u, resolver
->pending_requests().size());
1794 // Verify that requests ran as expected -- they should have fallen back to
1795 // the manual proxy configuration for HTTP urls.
1796 EXPECT_EQ(OK
, callback1
.WaitForResult());
1797 EXPECT_EQ("foopy:80", info1
.proxy_server().ToURI());
1799 EXPECT_EQ(OK
, callback2
.WaitForResult());
1800 EXPECT_EQ("foopy:80", info2
.proxy_server().ToURI());
1803 // Test that the bypass rules are NOT applied when using autodetect.
1804 TEST_F(ProxyServiceTest
, BypassDoesntApplyToPac
) {
1806 config
.set_auto_detect(true);
1807 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1808 config
.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
1809 config
.proxy_rules().bypass_rules
.ParseFromString("www.google.com");
1811 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1812 MockAsyncProxyResolverExpectsBytes
* resolver
=
1813 new MockAsyncProxyResolverExpectsBytes
;
1814 ProxyService
service(config_service
, resolver
, NULL
);
1816 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1817 service
.SetProxyScriptFetchers(fetcher
,
1818 new DoNothingDhcpProxyScriptFetcher());
1820 // Start 1 requests.
1823 TestCompletionCallback callback1
;
1824 int rv
= service
.ResolveProxy(
1825 GURL("http://www.google.com"), &info1
, callback1
.callback(), NULL
,
1827 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1829 // Check that nothing has been sent to the proxy resolver yet.
1830 ASSERT_EQ(0u, resolver
->pending_requests().size());
1832 // It should be trying to auto-detect first -- succeed the download.
1833 EXPECT_TRUE(fetcher
->has_pending_request());
1834 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1835 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1837 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1838 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1839 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1841 ASSERT_EQ(1u, resolver
->pending_requests().size());
1842 EXPECT_EQ(GURL("http://www.google.com"),
1843 resolver
->pending_requests()[0]->url());
1845 // Complete the pending request.
1846 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1847 resolver
->pending_requests()[0]->CompleteNow(OK
);
1849 // Verify that request ran as expected.
1850 EXPECT_EQ(OK
, callback1
.WaitForResult());
1851 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1853 // Start another request, it should pickup the bypass item.
1855 TestCompletionCallback callback2
;
1856 rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info2
,
1857 callback2
.callback(), NULL
, BoundNetLog());
1858 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1860 ASSERT_EQ(1u, resolver
->pending_requests().size());
1861 EXPECT_EQ(GURL("http://www.google.com"),
1862 resolver
->pending_requests()[0]->url());
1864 // Complete the pending request.
1865 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1866 resolver
->pending_requests()[0]->CompleteNow(OK
);
1868 EXPECT_EQ(OK
, callback2
.WaitForResult());
1869 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1872 // Delete the ProxyService while InitProxyResolver has an outstanding
1873 // request to the script fetcher. When run under valgrind, should not
1874 // have any memory errors (used to be that the ProxyScriptFetcher was
1875 // being deleted prior to the InitProxyResolver).
1876 TEST_F(ProxyServiceTest
, DeleteWhileInitProxyResolverHasOutstandingFetch
) {
1877 ProxyConfig config
=
1878 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
1880 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1881 MockAsyncProxyResolverExpectsBytes
* resolver
=
1882 new MockAsyncProxyResolverExpectsBytes
;
1883 ProxyService
service(config_service
, resolver
, NULL
);
1885 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1886 service
.SetProxyScriptFetchers(fetcher
,
1887 new DoNothingDhcpProxyScriptFetcher());
1892 TestCompletionCallback callback1
;
1893 int rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info1
,
1894 callback1
.callback(), NULL
, BoundNetLog());
1895 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1897 // Check that nothing has been sent to the proxy resolver yet.
1898 ASSERT_EQ(0u, resolver
->pending_requests().size());
1900 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
1901 // and be waiting on that to complete.
1902 EXPECT_TRUE(fetcher
->has_pending_request());
1903 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1906 // Delete the ProxyService while InitProxyResolver has an outstanding
1907 // request to the proxy resolver. When run under valgrind, should not
1908 // have any memory errors (used to be that the ProxyResolver was
1909 // being deleted prior to the InitProxyResolver).
1910 TEST_F(ProxyServiceTest
, DeleteWhileInitProxyResolverHasOutstandingSet
) {
1911 MockProxyConfigService
* config_service
=
1912 new MockProxyConfigService("http://foopy/proxy.pac");
1914 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
1916 ProxyService
service(config_service
, resolver
, NULL
);
1918 GURL
url("http://www.google.com/");
1921 TestCompletionCallback callback
;
1922 int rv
= service
.ResolveProxy(
1923 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
1924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1926 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1927 resolver
->pending_set_pac_script_request()->script_data()->url());
1930 TEST_F(ProxyServiceTest
, ResetProxyConfigService
) {
1931 ProxyConfig config1
;
1932 config1
.proxy_rules().ParseFromString("foopy1:8080");
1933 config1
.set_auto_detect(false);
1934 ProxyService
service(
1935 new MockProxyConfigService(config1
),
1936 new MockAsyncProxyResolverExpectsBytes
, NULL
);
1939 TestCompletionCallback callback1
;
1940 int rv
= service
.ResolveProxy(GURL("http://request1"), &info
,
1941 callback1
.callback(), NULL
, BoundNetLog());
1943 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1945 ProxyConfig config2
;
1946 config2
.proxy_rules().ParseFromString("foopy2:8080");
1947 config2
.set_auto_detect(false);
1948 service
.ResetConfigService(new MockProxyConfigService(config2
));
1949 TestCompletionCallback callback2
;
1950 rv
= service
.ResolveProxy(GURL("http://request2"), &info
,
1951 callback2
.callback(), NULL
, BoundNetLog());
1953 EXPECT_EQ("foopy2:8080", info
.proxy_server().ToURI());
1956 // Test that when going from a configuration that required PAC to one
1957 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
1958 TEST_F(ProxyServiceTest
, UpdateConfigFromPACToDirect
) {
1959 ProxyConfig config
= ProxyConfig::CreateAutoDetect();
1961 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1962 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
1963 ProxyService
service(config_service
, resolver
, NULL
);
1968 TestCompletionCallback callback1
;
1969 int rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info1
,
1970 callback1
.callback(), NULL
, BoundNetLog());
1971 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1973 // Check that nothing has been sent to the proxy resolver yet.
1974 ASSERT_EQ(0u, resolver
->pending_requests().size());
1976 // Successfully set the autodetect script.
1977 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT
,
1978 resolver
->pending_set_pac_script_request()->script_data()->type());
1979 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1981 // Complete the pending request.
1982 ASSERT_EQ(1u, resolver
->pending_requests().size());
1983 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1984 resolver
->pending_requests()[0]->CompleteNow(OK
);
1986 // Verify that request ran as expected.
1987 EXPECT_EQ(OK
, callback1
.WaitForResult());
1988 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1990 // Force the ProxyService to pull down a new proxy configuration.
1991 // (Even though the configuration isn't old/bad).
1993 // This new configuration no longer has auto_detect set, so
1994 // requests should complete synchronously now as direct-connect.
1995 config_service
->SetConfig(ProxyConfig::CreateDirect());
1997 // Start another request -- the effective configuration has changed.
1999 TestCompletionCallback callback2
;
2000 rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info2
,
2001 callback2
.callback(), NULL
, BoundNetLog());
2004 EXPECT_TRUE(info2
.is_direct());
2007 TEST_F(ProxyServiceTest
, NetworkChangeTriggersPacRefetch
) {
2008 MockProxyConfigService
* config_service
=
2009 new MockProxyConfigService("http://foopy/proxy.pac");
2011 MockAsyncProxyResolverExpectsBytes
* resolver
=
2012 new MockAsyncProxyResolverExpectsBytes
;
2014 CapturingNetLog log
;
2016 ProxyService
service(config_service
, resolver
, &log
);
2018 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2019 service
.SetProxyScriptFetchers(fetcher
,
2020 new DoNothingDhcpProxyScriptFetcher());
2022 // Disable the "wait after IP address changes" hack, so this unit-test can
2023 // complete quickly.
2024 service
.set_stall_proxy_auto_config_delay(base::TimeDelta());
2029 TestCompletionCallback callback1
;
2030 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
2031 callback1
.callback(), NULL
, BoundNetLog());
2032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2034 // The first request should have triggered initial download of PAC script.
2035 EXPECT_TRUE(fetcher
->has_pending_request());
2036 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2038 // Nothing has been sent to the resolver yet.
2039 EXPECT_TRUE(resolver
->pending_requests().empty());
2041 // At this point the ProxyService should be waiting for the
2042 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2043 // PAC script download completion.
2044 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2046 // Now that the PAC script is downloaded, the request will have been sent to
2047 // the proxy resolver.
2048 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2049 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2050 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2052 ASSERT_EQ(1u, resolver
->pending_requests().size());
2053 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2055 // Complete the pending request.
2056 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2057 resolver
->pending_requests()[0]->CompleteNow(OK
);
2059 // Wait for completion callback, and verify that the request ran as expected.
2060 EXPECT_EQ(OK
, callback1
.WaitForResult());
2061 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2063 // Now simluate a change in the network. The ProxyConfigService is still
2064 // going to return the same PAC URL as before, but this URL needs to be
2065 // refetched on the new network.
2066 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2067 MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2069 // Start a second request.
2071 TestCompletionCallback callback2
;
2072 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
2073 callback2
.callback(), NULL
, BoundNetLog());
2074 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2076 // This second request should have triggered the re-download of the PAC
2077 // script (since we marked the network as having changed).
2078 EXPECT_TRUE(fetcher
->has_pending_request());
2079 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2081 // Nothing has been sent to the resolver yet.
2082 EXPECT_TRUE(resolver
->pending_requests().empty());
2084 // Simulate the PAC script fetch as having completed (this time with
2086 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript2
);
2088 // Now that the PAC script is downloaded, the second request will have been
2089 // sent to the proxy resolver.
2090 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2
),
2091 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2092 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2094 ASSERT_EQ(1u, resolver
->pending_requests().size());
2095 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2097 // Complete the pending second request.
2098 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2099 resolver
->pending_requests()[0]->CompleteNow(OK
);
2101 // Wait for completion callback, and verify that the request ran as expected.
2102 EXPECT_EQ(OK
, callback2
.WaitForResult());
2103 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2105 // Check that the expected events were output to the log stream. In particular
2106 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2107 // setup), and NOT a second time when the IP address changed.
2108 CapturingNetLog::CapturedEntryList entries
;
2109 log
.GetEntries(&entries
);
2111 EXPECT_TRUE(LogContainsEntryWithType(entries
, 0,
2112 NetLog::TYPE_PROXY_CONFIG_CHANGED
));
2113 ASSERT_EQ(9u, entries
.size());
2114 for (size_t i
= 1; i
< entries
.size(); ++i
)
2115 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED
, entries
[i
].type
);
2118 // This test verifies that the PAC script specified by the settings is
2119 // periodically polled for changes. Specifically, if the initial fetch fails due
2120 // to a network error, we will eventually re-configure the service to use the
2121 // script once it becomes available.
2122 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterFailure
) {
2123 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2125 ImmediatePollPolicy poll_policy
;
2126 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2128 MockProxyConfigService
* config_service
=
2129 new MockProxyConfigService("http://foopy/proxy.pac");
2131 MockAsyncProxyResolverExpectsBytes
* resolver
=
2132 new MockAsyncProxyResolverExpectsBytes
;
2134 ProxyService
service(config_service
, resolver
, NULL
);
2136 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2137 service
.SetProxyScriptFetchers(fetcher
,
2138 new DoNothingDhcpProxyScriptFetcher());
2143 TestCompletionCallback callback1
;
2144 int rv
= service
.ResolveProxy(
2145 GURL("http://request1"), &info1
, callback1
.callback(),
2146 NULL
, BoundNetLog());
2147 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2149 // The first request should have triggered initial download of PAC script.
2150 EXPECT_TRUE(fetcher
->has_pending_request());
2151 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2153 // Nothing has been sent to the resolver yet.
2154 EXPECT_TRUE(resolver
->pending_requests().empty());
2156 // At this point the ProxyService should be waiting for the
2157 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2158 // PAC script download completion.
2160 // We simulate a failed download attempt, the proxy service should now
2161 // fall-back to DIRECT connections.
2162 fetcher
->NotifyFetchCompletion(ERR_FAILED
, "");
2164 ASSERT_TRUE(resolver
->pending_requests().empty());
2166 // Wait for completion callback, and verify it used DIRECT.
2167 EXPECT_EQ(OK
, callback1
.WaitForResult());
2168 EXPECT_TRUE(info1
.is_direct());
2170 // At this point we have initialized the proxy service using a PAC script,
2171 // however it failed and fell-back to DIRECT.
2173 // A background task to periodically re-check the PAC script for validity will
2174 // have been started. We will now wait for the next download attempt to start.
2176 // Note that we shouldn't have to wait long here, since our test enables a
2177 // special unit-test mode.
2178 fetcher
->WaitUntilFetch();
2180 ASSERT_TRUE(resolver
->pending_requests().empty());
2182 // Make sure that our background checker is trying to download the expected
2183 // PAC script (same one as before). This time we will simulate a successful
2184 // download of the script.
2185 EXPECT_TRUE(fetcher
->has_pending_request());
2186 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2187 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2189 MessageLoop::current()->RunUntilIdle();
2191 // Now that the PAC script is downloaded, it should be used to initialize the
2192 // ProxyResolver. Simulate a successful parse.
2193 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2194 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2195 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2197 // At this point the ProxyService should have re-configured itself to use the
2198 // PAC script (thereby recovering from the initial fetch failure). We will
2199 // verify that the next Resolve request uses the resolver rather than
2202 // Start a second request.
2204 TestCompletionCallback callback2
;
2205 rv
= service
.ResolveProxy(
2206 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2208 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2210 // Check that it was sent to the resolver.
2211 ASSERT_EQ(1u, resolver
->pending_requests().size());
2212 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2214 // Complete the pending second request.
2215 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2216 resolver
->pending_requests()[0]->CompleteNow(OK
);
2218 // Wait for completion callback, and verify that the request ran as expected.
2219 EXPECT_EQ(OK
, callback2
.WaitForResult());
2220 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2223 // This test verifies that the PAC script specified by the settings is
2224 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2225 // however at a later time its *contents* change, we will eventually
2226 // re-configure the service to use the new script.
2227 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterContentChange
) {
2228 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2230 ImmediatePollPolicy poll_policy
;
2231 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2233 MockProxyConfigService
* config_service
=
2234 new MockProxyConfigService("http://foopy/proxy.pac");
2236 MockAsyncProxyResolverExpectsBytes
* resolver
=
2237 new MockAsyncProxyResolverExpectsBytes
;
2239 ProxyService
service(config_service
, resolver
, NULL
);
2241 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2242 service
.SetProxyScriptFetchers(fetcher
,
2243 new DoNothingDhcpProxyScriptFetcher());
2248 TestCompletionCallback callback1
;
2249 int rv
= service
.ResolveProxy(
2250 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2252 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2254 // The first request should have triggered initial download of PAC script.
2255 EXPECT_TRUE(fetcher
->has_pending_request());
2256 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2258 // Nothing has been sent to the resolver yet.
2259 EXPECT_TRUE(resolver
->pending_requests().empty());
2261 // At this point the ProxyService should be waiting for the
2262 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2263 // PAC script download completion.
2264 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2266 // Now that the PAC script is downloaded, the request will have been sent to
2267 // the proxy resolver.
2268 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2269 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2270 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2272 ASSERT_EQ(1u, resolver
->pending_requests().size());
2273 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2275 // Complete the pending request.
2276 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2277 resolver
->pending_requests()[0]->CompleteNow(OK
);
2279 // Wait for completion callback, and verify that the request ran as expected.
2280 EXPECT_EQ(OK
, callback1
.WaitForResult());
2281 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2283 // At this point we have initialized the proxy service using a PAC script.
2285 // A background task to periodically re-check the PAC script for validity will
2286 // have been started. We will now wait for the next download attempt to start.
2288 // Note that we shouldn't have to wait long here, since our test enables a
2289 // special unit-test mode.
2290 fetcher
->WaitUntilFetch();
2292 ASSERT_TRUE(resolver
->pending_requests().empty());
2294 // Make sure that our background checker is trying to download the expected
2295 // PAC script (same one as before). This time we will simulate a successful
2296 // download of a DIFFERENT script.
2297 EXPECT_TRUE(fetcher
->has_pending_request());
2298 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2299 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript2
);
2301 MessageLoop::current()->RunUntilIdle();
2303 // Now that the PAC script is downloaded, it should be used to initialize the
2304 // ProxyResolver. Simulate a successful parse.
2305 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2
),
2306 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2307 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2309 // At this point the ProxyService should have re-configured itself to use the
2312 // Start a second request.
2314 TestCompletionCallback callback2
;
2315 rv
= service
.ResolveProxy(
2316 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2318 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2320 // Check that it was sent to the resolver.
2321 ASSERT_EQ(1u, resolver
->pending_requests().size());
2322 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2324 // Complete the pending second request.
2325 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2326 resolver
->pending_requests()[0]->CompleteNow(OK
);
2328 // Wait for completion callback, and verify that the request ran as expected.
2329 EXPECT_EQ(OK
, callback2
.WaitForResult());
2330 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2333 // This test verifies that the PAC script specified by the settings is
2334 // periodically polled for changes. Specifically, if the initial fetch succeeds
2335 // and so does the next poll, however the contents of the downloaded script
2336 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2337 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterContentUnchanged
) {
2338 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2340 ImmediatePollPolicy poll_policy
;
2341 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2343 MockProxyConfigService
* config_service
=
2344 new MockProxyConfigService("http://foopy/proxy.pac");
2346 MockAsyncProxyResolverExpectsBytes
* resolver
=
2347 new MockAsyncProxyResolverExpectsBytes
;
2349 ProxyService
service(config_service
, resolver
, NULL
);
2351 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2352 service
.SetProxyScriptFetchers(fetcher
,
2353 new DoNothingDhcpProxyScriptFetcher());
2358 TestCompletionCallback callback1
;
2359 int rv
= service
.ResolveProxy(
2360 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2362 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2364 // The first request should have triggered initial download of PAC script.
2365 EXPECT_TRUE(fetcher
->has_pending_request());
2366 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2368 // Nothing has been sent to the resolver yet.
2369 EXPECT_TRUE(resolver
->pending_requests().empty());
2371 // At this point the ProxyService should be waiting for the
2372 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2373 // PAC script download completion.
2374 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2376 // Now that the PAC script is downloaded, the request will have been sent to
2377 // the proxy resolver.
2378 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2379 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2380 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2382 ASSERT_EQ(1u, resolver
->pending_requests().size());
2383 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2385 // Complete the pending request.
2386 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2387 resolver
->pending_requests()[0]->CompleteNow(OK
);
2389 // Wait for completion callback, and verify that the request ran as expected.
2390 EXPECT_EQ(OK
, callback1
.WaitForResult());
2391 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2393 // At this point we have initialized the proxy service using a PAC script.
2395 // A background task to periodically re-check the PAC script for validity will
2396 // have been started. We will now wait for the next download attempt to start.
2398 // Note that we shouldn't have to wait long here, since our test enables a
2399 // special unit-test mode.
2400 fetcher
->WaitUntilFetch();
2402 ASSERT_TRUE(resolver
->pending_requests().empty());
2404 // Make sure that our background checker is trying to download the expected
2405 // PAC script (same one as before). We will simulate the same response as
2406 // last time (i.e. the script is unchanged).
2407 EXPECT_TRUE(fetcher
->has_pending_request());
2408 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2409 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2411 MessageLoop::current()->RunUntilIdle();
2413 ASSERT_FALSE(resolver
->has_pending_set_pac_script_request());
2415 // At this point the ProxyService is still running the same PAC script as
2418 // Start a second request.
2420 TestCompletionCallback callback2
;
2421 rv
= service
.ResolveProxy(
2422 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2424 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2426 // Check that it was sent to the resolver.
2427 ASSERT_EQ(1u, resolver
->pending_requests().size());
2428 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2430 // Complete the pending second request.
2431 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2432 resolver
->pending_requests()[0]->CompleteNow(OK
);
2434 // Wait for completion callback, and verify that the request ran as expected.
2435 EXPECT_EQ(OK
, callback2
.WaitForResult());
2436 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2439 // This test verifies that the PAC script specified by the settings is
2440 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2441 // however at a later time it starts to fail, we should re-configure the
2442 // ProxyService to stop using that PAC script.
2443 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterSuccess
) {
2444 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2446 ImmediatePollPolicy poll_policy
;
2447 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2449 MockProxyConfigService
* config_service
=
2450 new MockProxyConfigService("http://foopy/proxy.pac");
2452 MockAsyncProxyResolverExpectsBytes
* resolver
=
2453 new MockAsyncProxyResolverExpectsBytes
;
2455 ProxyService
service(config_service
, resolver
, NULL
);
2457 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2458 service
.SetProxyScriptFetchers(fetcher
,
2459 new DoNothingDhcpProxyScriptFetcher());
2464 TestCompletionCallback callback1
;
2465 int rv
= service
.ResolveProxy(
2466 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2470 // The first request should have triggered initial download of PAC script.
2471 EXPECT_TRUE(fetcher
->has_pending_request());
2472 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2474 // Nothing has been sent to the resolver yet.
2475 EXPECT_TRUE(resolver
->pending_requests().empty());
2477 // At this point the ProxyService should be waiting for the
2478 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2479 // PAC script download completion.
2480 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2482 // Now that the PAC script is downloaded, the request will have been sent to
2483 // the proxy resolver.
2484 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2485 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2486 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2488 ASSERT_EQ(1u, resolver
->pending_requests().size());
2489 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2491 // Complete the pending request.
2492 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2493 resolver
->pending_requests()[0]->CompleteNow(OK
);
2495 // Wait for completion callback, and verify that the request ran as expected.
2496 EXPECT_EQ(OK
, callback1
.WaitForResult());
2497 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2499 // At this point we have initialized the proxy service using a PAC script.
2501 // A background task to periodically re-check the PAC script for validity will
2502 // have been started. We will now wait for the next download attempt to start.
2504 // Note that we shouldn't have to wait long here, since our test enables a
2505 // special unit-test mode.
2506 fetcher
->WaitUntilFetch();
2508 ASSERT_TRUE(resolver
->pending_requests().empty());
2510 // Make sure that our background checker is trying to download the expected
2511 // PAC script (same one as before). This time we will simulate a failure
2512 // to download the script.
2513 EXPECT_TRUE(fetcher
->has_pending_request());
2514 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2515 fetcher
->NotifyFetchCompletion(ERR_FAILED
, "");
2517 MessageLoop::current()->RunUntilIdle();
2519 // At this point the ProxyService should have re-configured itself to use
2520 // DIRECT connections rather than the given proxy resolver.
2522 // Start a second request.
2524 TestCompletionCallback callback2
;
2525 rv
= service
.ResolveProxy(
2526 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2529 EXPECT_TRUE(info2
.is_direct());
2532 // Tests that the code which decides at what times to poll the PAC
2533 // script follows the expected policy.
2534 TEST_F(ProxyServiceTest
, PACScriptPollingPolicy
) {
2535 // Retrieve the internal polling policy implementation used by ProxyService.
2536 scoped_ptr
<ProxyService::PacPollPolicy
> policy
=
2537 ProxyService::CreateDefaultPacPollPolicy();
2540 ProxyService::PacPollPolicy::Mode mode
;
2541 const base::TimeDelta initial_delay
= base::TimeDelta::FromMilliseconds(-1);
2542 base::TimeDelta delay
= initial_delay
;
2544 // --------------------------------------------------
2545 // Test the poll sequence in response to a failure.
2546 // --------------------------------------------------
2547 error
= ERR_NAME_NOT_RESOLVED
;
2550 mode
= policy
->GetNextDelay(error
, initial_delay
, &delay
);
2551 EXPECT_EQ(8, delay
.InSeconds());
2552 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER
, mode
);
2555 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2556 EXPECT_EQ(32, delay
.InSeconds());
2557 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2560 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2561 EXPECT_EQ(120, delay
.InSeconds());
2562 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2565 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2566 EXPECT_EQ(14400, delay
.InSeconds());
2567 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2570 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2571 EXPECT_EQ(14400, delay
.InSeconds());
2572 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2574 // --------------------------------------------------
2575 // Test the poll sequence in response to a success.
2576 // --------------------------------------------------
2580 mode
= policy
->GetNextDelay(error
, initial_delay
, &delay
);
2581 EXPECT_EQ(43200, delay
.InSeconds());
2582 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2585 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2586 EXPECT_EQ(43200, delay
.InSeconds());
2587 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2590 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2591 EXPECT_EQ(43200, delay
.InSeconds());
2592 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2595 // This tests the polling of the PAC script. Specifically, it tests that
2596 // polling occurs in response to user activity.
2597 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterActivity
) {
2598 ImmediateAfterActivityPollPolicy poll_policy
;
2599 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2601 MockProxyConfigService
* config_service
=
2602 new MockProxyConfigService("http://foopy/proxy.pac");
2604 MockAsyncProxyResolverExpectsBytes
* resolver
=
2605 new MockAsyncProxyResolverExpectsBytes
;
2607 ProxyService
service(config_service
, resolver
, NULL
);
2609 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2610 service
.SetProxyScriptFetchers(fetcher
,
2611 new DoNothingDhcpProxyScriptFetcher());
2616 TestCompletionCallback callback1
;
2617 int rv
= service
.ResolveProxy(
2618 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2620 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2622 // The first request should have triggered initial download of PAC script.
2623 EXPECT_TRUE(fetcher
->has_pending_request());
2624 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2626 // Nothing has been sent to the resolver yet.
2627 EXPECT_TRUE(resolver
->pending_requests().empty());
2629 // At this point the ProxyService should be waiting for the
2630 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2631 // PAC script download completion.
2632 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2634 // Now that the PAC script is downloaded, the request will have been sent to
2635 // the proxy resolver.
2636 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2637 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2638 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2640 ASSERT_EQ(1u, resolver
->pending_requests().size());
2641 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2643 // Complete the pending request.
2644 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2645 resolver
->pending_requests()[0]->CompleteNow(OK
);
2647 // Wait for completion callback, and verify that the request ran as expected.
2648 EXPECT_EQ(OK
, callback1
.WaitForResult());
2649 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2651 // At this point we have initialized the proxy service using a PAC script.
2652 // Our PAC poller is set to update ONLY in response to network activity,
2653 // (i.e. another call to ResolveProxy()).
2655 ASSERT_FALSE(fetcher
->has_pending_request());
2656 ASSERT_TRUE(resolver
->pending_requests().empty());
2658 // Start a second request.
2660 TestCompletionCallback callback2
;
2661 rv
= service
.ResolveProxy(
2662 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2664 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2666 // This request should have sent work to the resolver; complete it.
2667 ASSERT_EQ(1u, resolver
->pending_requests().size());
2668 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2669 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2670 resolver
->pending_requests()[0]->CompleteNow(OK
);
2672 EXPECT_EQ(OK
, callback2
.WaitForResult());
2673 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2675 // In response to getting that resolve request, the poller should have
2676 // started the next poll, and made it as far as to request the download.
2678 EXPECT_TRUE(fetcher
->has_pending_request());
2679 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2681 // This time we will fail the download, to simulate a PAC script change.
2682 fetcher
->NotifyFetchCompletion(ERR_FAILED
, "");
2684 // Drain the message loop, so ProxyService is notified of the change
2685 // and has a chance to re-configure itself.
2686 MessageLoop::current()->RunUntilIdle();
2688 // Start a third request -- this time we expect to get a direct connection
2689 // since the PAC script poller experienced a failure.
2691 TestCompletionCallback callback3
;
2692 rv
= service
.ResolveProxy(
2693 GURL("http://request3"), &info3
, callback3
.callback(), NULL
,
2696 EXPECT_TRUE(info3
.is_direct());