1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/proxy/proxy_service.h"
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/net_log.h"
15 #include "net/base/net_log_unittest.h"
16 #include "net/base/test_completion_callback.h"
17 #include "net/proxy/dhcp_proxy_script_fetcher.h"
18 #include "net/proxy/mock_proxy_resolver.h"
19 #include "net/proxy/mock_proxy_script_fetcher.h"
20 #include "net/proxy/proxy_config_service.h"
21 #include "net/proxy/proxy_resolver.h"
22 #include "net/proxy/proxy_script_fetcher.h"
23 #include "testing/gtest/include/gtest/gtest.h"
26 using base::ASCIIToUTF16
;
28 // TODO(eroman): Write a test which exercises
29 // ProxyService::SuspendAllPendingRequests().
33 // This polling policy will decide to poll every 1 ms.
34 class ImmediatePollPolicy
: public ProxyService::PacPollPolicy
{
36 ImmediatePollPolicy() {}
38 virtual Mode
GetNextDelay(int error
, base::TimeDelta current_delay
,
39 base::TimeDelta
* next_delay
) const OVERRIDE
{
40 *next_delay
= base::TimeDelta::FromMilliseconds(1);
41 return MODE_USE_TIMER
;
45 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy
);
48 // This polling policy chooses a fantastically large delay. In other words, it
49 // will never trigger a poll
50 class NeverPollPolicy
: public ProxyService::PacPollPolicy
{
54 virtual Mode
GetNextDelay(int error
, base::TimeDelta current_delay
,
55 base::TimeDelta
* next_delay
) const OVERRIDE
{
56 *next_delay
= base::TimeDelta::FromDays(60);
57 return MODE_USE_TIMER
;
61 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy
);
64 // This polling policy starts a poll immediately after network activity.
65 class ImmediateAfterActivityPollPolicy
: public ProxyService::PacPollPolicy
{
67 ImmediateAfterActivityPollPolicy() {}
69 virtual Mode
GetNextDelay(int error
, base::TimeDelta current_delay
,
70 base::TimeDelta
* next_delay
) const OVERRIDE
{
71 *next_delay
= base::TimeDelta();
72 return MODE_START_AFTER_ACTIVITY
;
76 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy
);
79 // This test fixture is used to partially disable the background polling done by
80 // the ProxyService (which it uses to detect whenever its PAC script contents or
81 // WPAD results have changed).
83 // We disable the feature by setting the poll interval to something really
84 // large, so it will never actually be reached even on the slowest bots that run
87 // We disable the polling in order to avoid any timing dependencies in the
88 // tests. If the bot were to run the tests very slowly and we hadn't disabled
89 // polling, then it might start a background re-try in the middle of our test
90 // and confuse our expectations leading to flaky failures.
92 // The tests which verify the polling code re-enable the polling behavior but
93 // are careful to avoid timing problems.
94 class ProxyServiceTest
: public testing::Test
{
96 virtual void SetUp() OVERRIDE
{
97 testing::Test::SetUp();
99 ProxyService::set_pac_script_poll_policy(&never_poll_policy_
);
102 virtual void TearDown() OVERRIDE
{
103 // Restore the original policy.
104 ProxyService::set_pac_script_poll_policy(previous_policy_
);
105 testing::Test::TearDown();
109 NeverPollPolicy never_poll_policy_
;
110 const ProxyService::PacPollPolicy
* previous_policy_
;
113 const char kValidPacScript1
[] = "pac-script-v1-FindProxyForURL";
114 const char kValidPacScript2
[] = "pac-script-v2-FindProxyForURL";
116 class MockProxyConfigService
: public ProxyConfigService
{
118 explicit MockProxyConfigService(const ProxyConfig
& config
)
119 : availability_(CONFIG_VALID
),
123 explicit MockProxyConfigService(const std::string
& pac_url
)
124 : availability_(CONFIG_VALID
),
125 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url
))) {
128 virtual void AddObserver(Observer
* observer
) OVERRIDE
{
129 observers_
.AddObserver(observer
);
132 virtual void RemoveObserver(Observer
* observer
) OVERRIDE
{
133 observers_
.RemoveObserver(observer
);
136 virtual ConfigAvailability
GetLatestProxyConfig(ProxyConfig
* results
)
138 if (availability_
== CONFIG_VALID
)
140 return availability_
;
143 void SetConfig(const ProxyConfig
& config
) {
144 availability_
= CONFIG_VALID
;
146 FOR_EACH_OBSERVER(Observer
, observers_
,
147 OnProxyConfigChanged(config_
, availability_
));
151 ConfigAvailability availability_
;
153 ObserverList
<Observer
, true> observers_
;
158 TEST_F(ProxyServiceTest
, Direct
) {
159 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
160 ProxyService
service(new MockProxyConfigService(
161 ProxyConfig::CreateDirect()), resolver
, NULL
);
163 GURL
url("http://www.google.com/");
166 TestCompletionCallback callback
;
167 CapturingBoundNetLog log
;
168 int rv
= service
.ResolveProxy(
169 url
, &info
, callback
.callback(), NULL
, log
.bound());
171 EXPECT_TRUE(resolver
->pending_requests().empty());
173 EXPECT_TRUE(info
.is_direct());
174 EXPECT_TRUE(info
.proxy_resolve_start_time().is_null());
175 EXPECT_TRUE(info
.proxy_resolve_end_time().is_null());
177 // Check the NetLog was filled correctly.
178 CapturingNetLog::CapturedEntryList entries
;
179 log
.GetEntries(&entries
);
181 EXPECT_EQ(3u, entries
.size());
182 EXPECT_TRUE(LogContainsBeginEvent(
183 entries
, 0, NetLog::TYPE_PROXY_SERVICE
));
184 EXPECT_TRUE(LogContainsEvent(
185 entries
, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST
,
186 NetLog::PHASE_NONE
));
187 EXPECT_TRUE(LogContainsEndEvent(
188 entries
, 2, NetLog::TYPE_PROXY_SERVICE
));
191 TEST_F(ProxyServiceTest
, PAC
) {
192 MockProxyConfigService
* config_service
=
193 new MockProxyConfigService("http://foopy/proxy.pac");
195 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
197 ProxyService
service(config_service
, resolver
, NULL
);
199 GURL
url("http://www.google.com/");
202 TestCompletionCallback callback
;
203 ProxyService::PacRequest
* request
;
204 CapturingBoundNetLog log
;
206 int rv
= service
.ResolveProxy(
207 url
, &info
, callback
.callback(), &request
, log
.bound());
208 EXPECT_EQ(ERR_IO_PENDING
, rv
);
210 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request
));
212 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
213 resolver
->pending_set_pac_script_request()->script_data()->url());
214 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
216 ASSERT_EQ(1u, resolver
->pending_requests().size());
217 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
219 // Set the result in proxy resolver.
220 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy");
221 resolver
->pending_requests()[0]->CompleteNow(OK
);
223 EXPECT_EQ(OK
, callback
.WaitForResult());
224 EXPECT_FALSE(info
.is_direct());
225 EXPECT_EQ("foopy:80", info
.proxy_server().ToURI());
226 EXPECT_TRUE(info
.did_use_pac_script());
228 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
229 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
230 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
232 // Check the NetLog was filled correctly.
233 CapturingNetLog::CapturedEntryList entries
;
234 log
.GetEntries(&entries
);
236 EXPECT_EQ(5u, entries
.size());
237 EXPECT_TRUE(LogContainsBeginEvent(
238 entries
, 0, NetLog::TYPE_PROXY_SERVICE
));
239 EXPECT_TRUE(LogContainsBeginEvent(
240 entries
, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
241 EXPECT_TRUE(LogContainsEndEvent(
242 entries
, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
243 EXPECT_TRUE(LogContainsEndEvent(
244 entries
, 4, NetLog::TYPE_PROXY_SERVICE
));
247 // Test that the proxy resolver does not see the URL's username/password
248 // or its reference section.
249 TEST_F(ProxyServiceTest
, PAC_NoIdentityOrHash
) {
250 MockProxyConfigService
* config_service
=
251 new MockProxyConfigService("http://foopy/proxy.pac");
253 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
255 ProxyService
service(config_service
, resolver
, NULL
);
257 GURL
url("http://username:password@www.google.com/?ref#hash#hash");
260 TestCompletionCallback callback
;
261 int rv
= service
.ResolveProxy(
262 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
263 EXPECT_EQ(ERR_IO_PENDING
, rv
);
265 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
266 resolver
->pending_set_pac_script_request()->script_data()->url());
267 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
269 ASSERT_EQ(1u, resolver
->pending_requests().size());
270 // The URL should have been simplified, stripping the username/password/hash.
271 EXPECT_EQ(GURL("http://www.google.com/?ref"),
272 resolver
->pending_requests()[0]->url());
274 // We end here without ever completing the request -- destruction of
275 // ProxyService will cancel the outstanding request.
278 TEST_F(ProxyServiceTest
, PAC_FailoverWithoutDirect
) {
279 MockProxyConfigService
* config_service
=
280 new MockProxyConfigService("http://foopy/proxy.pac");
281 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
283 ProxyService
service(config_service
, resolver
, NULL
);
285 GURL
url("http://www.google.com/");
288 TestCompletionCallback callback1
;
289 int rv
= service
.ResolveProxy(
290 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
291 EXPECT_EQ(ERR_IO_PENDING
, rv
);
293 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
294 resolver
->pending_set_pac_script_request()->script_data()->url());
295 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
297 ASSERT_EQ(1u, resolver
->pending_requests().size());
298 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
300 // Set the result in proxy resolver.
301 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
302 resolver
->pending_requests()[0]->CompleteNow(OK
);
304 EXPECT_EQ(OK
, callback1
.WaitForResult());
305 EXPECT_FALSE(info
.is_direct());
306 EXPECT_EQ("foopy:8080", info
.proxy_server().ToURI());
307 EXPECT_TRUE(info
.did_use_pac_script());
309 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
310 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
311 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
313 // Now, imagine that connecting to foopy:8080 fails: there is nothing
314 // left to fallback to, since our proxy list was NOT terminated by
316 TestCompletionCallback callback2
;
317 rv
= service
.ReconsiderProxyAfterError(
318 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
319 // ReconsiderProxyAfterError returns error indicating nothing left.
320 EXPECT_EQ(ERR_FAILED
, rv
);
321 EXPECT_TRUE(info
.is_empty());
324 // Test that if the execution of the PAC script fails (i.e. javascript runtime
325 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
326 TEST_F(ProxyServiceTest
, PAC_RuntimeError
) {
327 MockProxyConfigService
* config_service
=
328 new MockProxyConfigService("http://foopy/proxy.pac");
329 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
331 ProxyService
service(config_service
, resolver
, NULL
);
333 GURL
url("http://this-causes-js-error/");
336 TestCompletionCallback callback1
;
337 int rv
= service
.ResolveProxy(
338 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
341 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
342 resolver
->pending_set_pac_script_request()->script_data()->url());
343 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
345 ASSERT_EQ(1u, resolver
->pending_requests().size());
346 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
348 // Simulate a failure in the PAC executor.
349 resolver
->pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED
);
351 EXPECT_EQ(OK
, callback1
.WaitForResult());
353 // Since the PAC script was non-mandatory, we should have fallen-back to
355 EXPECT_TRUE(info
.is_direct());
356 EXPECT_TRUE(info
.did_use_pac_script());
357 EXPECT_EQ(1, info
.config_id());
359 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
360 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
361 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
364 // The proxy list could potentially contain the DIRECT fallback choice
365 // in a location other than the very end of the list, and could even
366 // specify it multiple times.
368 // This is not a typical usage, but we will obey it.
369 // (If we wanted to disallow this type of input, the right place to
370 // enforce it would be in parsing the PAC result string).
372 // This test will use the PAC result string:
374 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
376 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
377 // then foobar:20, and then give up and error.
379 // The important check of this test is to make sure that DIRECT is not somehow
380 // cached as being a bad proxy.
381 TEST_F(ProxyServiceTest
, PAC_FailoverAfterDirect
) {
382 MockProxyConfigService
* config_service
=
383 new MockProxyConfigService("http://foopy/proxy.pac");
384 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
386 ProxyService
service(config_service
, resolver
, NULL
);
388 GURL
url("http://www.google.com/");
391 TestCompletionCallback callback1
;
392 int rv
= service
.ResolveProxy(
393 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
394 EXPECT_EQ(ERR_IO_PENDING
, rv
);
396 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
397 resolver
->pending_set_pac_script_request()->script_data()->url());
398 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
400 ASSERT_EQ(1u, resolver
->pending_requests().size());
401 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
403 // Set the result in proxy resolver.
404 resolver
->pending_requests()[0]->results()->UsePacString(
405 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
406 resolver
->pending_requests()[0]->CompleteNow(OK
);
408 EXPECT_EQ(OK
, callback1
.WaitForResult());
409 EXPECT_TRUE(info
.is_direct());
412 TestCompletionCallback callback2
;
413 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
416 EXPECT_FALSE(info
.is_direct());
417 EXPECT_EQ("foobar:10", info
.proxy_server().ToURI());
420 TestCompletionCallback callback3
;
421 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback3
.callback(), NULL
,
424 EXPECT_TRUE(info
.is_direct());
427 TestCompletionCallback callback4
;
428 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
431 EXPECT_FALSE(info
.is_direct());
432 EXPECT_EQ("foobar:20", info
.proxy_server().ToURI());
434 // Fallback 4 -- Nothing to fall back to!
435 TestCompletionCallback callback5
;
436 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback5
.callback(), NULL
,
438 EXPECT_EQ(ERR_FAILED
, rv
);
439 EXPECT_TRUE(info
.is_empty());
442 TEST_F(ProxyServiceTest
, PAC_ConfigSourcePropagates
) {
443 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
444 // to ProxyInfo after the proxy is resolved via a PAC script.
446 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
447 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
449 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
450 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
451 ProxyService
service(config_service
, resolver
, NULL
);
453 // Resolve something.
454 GURL
url("http://www.google.com/");
456 TestCompletionCallback callback
;
457 int rv
= service
.ResolveProxy(
458 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
459 ASSERT_EQ(ERR_IO_PENDING
, rv
);
460 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
461 ASSERT_EQ(1u, resolver
->pending_requests().size());
463 // Set the result in proxy resolver.
464 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy");
465 resolver
->pending_requests()[0]->CompleteNow(OK
);
467 EXPECT_EQ(OK
, callback
.WaitForResult());
468 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
469 EXPECT_TRUE(info
.did_use_pac_script());
471 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
472 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
473 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
476 TEST_F(ProxyServiceTest
, ProxyResolverFails
) {
477 // Test what happens when the ProxyResolver fails. The download and setting
478 // of the PAC script have already succeeded, so this corresponds with a
479 // javascript runtime error while calling FindProxyForURL().
481 MockProxyConfigService
* config_service
=
482 new MockProxyConfigService("http://foopy/proxy.pac");
484 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
486 ProxyService
service(config_service
, resolver
, NULL
);
488 // Start first resolve request.
489 GURL
url("http://www.google.com/");
491 TestCompletionCallback callback1
;
492 int rv
= service
.ResolveProxy(
493 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
494 EXPECT_EQ(ERR_IO_PENDING
, rv
);
496 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
497 resolver
->pending_set_pac_script_request()->script_data()->url());
498 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
500 ASSERT_EQ(1u, resolver
->pending_requests().size());
501 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
503 // Fail the first resolve request in MockAsyncProxyResolver.
504 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
506 // Although the proxy resolver failed the request, ProxyService implicitly
507 // falls-back to DIRECT.
508 EXPECT_EQ(OK
, callback1
.WaitForResult());
509 EXPECT_TRUE(info
.is_direct());
511 // Failed PAC executions still have proxy resolution times.
512 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
513 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
514 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
516 // The second resolve request will try to run through the proxy resolver,
517 // regardless of whether the first request failed in it.
518 TestCompletionCallback callback2
;
519 rv
= service
.ResolveProxy(
520 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
521 EXPECT_EQ(ERR_IO_PENDING
, rv
);
523 ASSERT_EQ(1u, resolver
->pending_requests().size());
524 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
526 // This time we will have the resolver succeed (perhaps the PAC script has
527 // a dependency on the current time).
528 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
529 resolver
->pending_requests()[0]->CompleteNow(OK
);
531 EXPECT_EQ(OK
, callback2
.WaitForResult());
532 EXPECT_FALSE(info
.is_direct());
533 EXPECT_EQ("foopy_valid:8080", info
.proxy_server().ToURI());
536 TEST_F(ProxyServiceTest
, ProxyScriptFetcherFailsDownloadingMandatoryPac
) {
537 // Test what happens when the ProxyScriptResolver fails to download a
538 // mandatory PAC script.
541 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
542 config
.set_pac_mandatory(true);
544 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
546 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
548 ProxyService
service(config_service
, resolver
, NULL
);
550 // Start first resolve request.
551 GURL
url("http://www.google.com/");
553 TestCompletionCallback callback1
;
554 int rv
= service
.ResolveProxy(
555 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
558 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
559 resolver
->pending_set_pac_script_request()->script_data()->url());
560 resolver
->pending_set_pac_script_request()->CompleteNow(ERR_FAILED
);
562 ASSERT_EQ(0u, resolver
->pending_requests().size());
564 // As the proxy resolver failed the request and is configured for a mandatory
565 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
566 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
567 callback1
.WaitForResult());
568 EXPECT_FALSE(info
.is_direct());
570 // As the proxy resolver failed the request and is configured for a mandatory
571 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
572 TestCompletionCallback callback2
;
573 rv
= service
.ResolveProxy(
574 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
575 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
, rv
);
576 EXPECT_FALSE(info
.is_direct());
579 TEST_F(ProxyServiceTest
, ProxyResolverFailsParsingJavaScriptMandatoryPac
) {
580 // Test what happens when the ProxyResolver fails that is configured to use a
581 // mandatory PAC script. The download of the PAC script has already
582 // succeeded but the PAC script contains no valid javascript.
585 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
586 config
.set_pac_mandatory(true);
588 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
590 MockAsyncProxyResolverExpectsBytes
* resolver
=
591 new MockAsyncProxyResolverExpectsBytes
;
593 ProxyService
service(config_service
, resolver
, NULL
);
595 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
596 DhcpProxyScriptFetcher
* dhcp_fetcher
= new DoNothingDhcpProxyScriptFetcher();
597 service
.SetProxyScriptFetchers(fetcher
, dhcp_fetcher
);
599 // Start resolve request.
600 GURL
url("http://www.google.com/");
602 TestCompletionCallback callback
;
603 int rv
= service
.ResolveProxy(
604 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
605 EXPECT_EQ(ERR_IO_PENDING
, rv
);
607 // Check that nothing has been sent to the proxy resolver yet.
608 ASSERT_EQ(0u, resolver
->pending_requests().size());
610 // Downloading the PAC script succeeds.
611 EXPECT_TRUE(fetcher
->has_pending_request());
612 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
613 fetcher
->NotifyFetchCompletion(OK
, "invalid-script-contents");
615 EXPECT_FALSE(fetcher
->has_pending_request());
616 ASSERT_EQ(0u, resolver
->pending_requests().size());
618 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
619 // mandatory for this configuration, the ProxyService must not implicitly
620 // fall-back to DIRECT.
621 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
622 callback
.WaitForResult());
623 EXPECT_FALSE(info
.is_direct());
626 TEST_F(ProxyServiceTest
, ProxyResolverFailsInJavaScriptMandatoryPac
) {
627 // Test what happens when the ProxyResolver fails that is configured to use a
628 // mandatory PAC script. The download and setting of the PAC script have
629 // already succeeded, so this corresponds with a javascript runtime error
630 // while calling FindProxyForURL().
633 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
634 config
.set_pac_mandatory(true);
636 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
638 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
640 ProxyService
service(config_service
, resolver
, NULL
);
642 // Start first resolve request.
643 GURL
url("http://www.google.com/");
645 TestCompletionCallback callback1
;
646 int rv
= service
.ResolveProxy(
647 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
648 EXPECT_EQ(ERR_IO_PENDING
, rv
);
650 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
651 resolver
->pending_set_pac_script_request()->script_data()->url());
652 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
654 ASSERT_EQ(1u, resolver
->pending_requests().size());
655 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
657 // Fail the first resolve request in MockAsyncProxyResolver.
658 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
660 // As the proxy resolver failed the request and is configured for a mandatory
661 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
662 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
663 callback1
.WaitForResult());
664 EXPECT_FALSE(info
.is_direct());
666 // The second resolve request will try to run through the proxy resolver,
667 // regardless of whether the first request failed in it.
668 TestCompletionCallback callback2
;
669 rv
= service
.ResolveProxy(
670 url
, &info
, callback2
.callback(), NULL
, BoundNetLog());
671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
673 ASSERT_EQ(1u, resolver
->pending_requests().size());
674 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
676 // This time we will have the resolver succeed (perhaps the PAC script has
677 // a dependency on the current time).
678 resolver
->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
679 resolver
->pending_requests()[0]->CompleteNow(OK
);
681 EXPECT_EQ(OK
, callback2
.WaitForResult());
682 EXPECT_FALSE(info
.is_direct());
683 EXPECT_EQ("foopy_valid:8080", info
.proxy_server().ToURI());
686 TEST_F(ProxyServiceTest
, ProxyFallback
) {
687 // Test what happens when we specify multiple proxy servers and some of them
690 MockProxyConfigService
* config_service
=
691 new MockProxyConfigService("http://foopy/proxy.pac");
693 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
695 ProxyService
service(config_service
, resolver
, NULL
);
697 GURL
url("http://www.google.com/");
699 // Get the proxy information.
701 TestCompletionCallback callback1
;
702 int rv
= service
.ResolveProxy(
703 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
704 EXPECT_EQ(ERR_IO_PENDING
, rv
);
706 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
707 resolver
->pending_set_pac_script_request()->script_data()->url());
708 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
710 ASSERT_EQ(1u, resolver
->pending_requests().size());
711 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
713 // Set the result in proxy resolver.
714 resolver
->pending_requests()[0]->results()->UseNamedProxy(
715 "foopy1:8080;foopy2:9090");
716 resolver
->pending_requests()[0]->CompleteNow(OK
);
718 // The first item is valid.
719 EXPECT_EQ(OK
, callback1
.WaitForResult());
720 EXPECT_FALSE(info
.is_direct());
721 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
723 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
724 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
725 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
726 base::TimeTicks proxy_resolve_start_time
= info
.proxy_resolve_start_time();
727 base::TimeTicks proxy_resolve_end_time
= info
.proxy_resolve_end_time();
729 // Fake an error on the proxy.
730 TestCompletionCallback callback2
;
731 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
735 // Proxy times should not have been modified by fallback.
736 EXPECT_EQ(proxy_resolve_start_time
, info
.proxy_resolve_start_time());
737 EXPECT_EQ(proxy_resolve_end_time
, info
.proxy_resolve_end_time());
739 // The second proxy should be specified.
740 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
741 // Report back that the second proxy worked. This will globally mark the
742 // first proxy as bad.
743 service
.ReportSuccess(info
);
745 TestCompletionCallback callback3
;
746 rv
= service
.ResolveProxy(
747 url
, &info
, callback3
.callback(), NULL
, BoundNetLog());
748 EXPECT_EQ(ERR_IO_PENDING
, rv
);
750 ASSERT_EQ(1u, resolver
->pending_requests().size());
751 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
753 // Set the result in proxy resolver -- the second result is already known
754 // to be bad, so we will not try to use it initially.
755 resolver
->pending_requests()[0]->results()->UseNamedProxy(
756 "foopy3:7070;foopy1:8080;foopy2:9090");
757 resolver
->pending_requests()[0]->CompleteNow(OK
);
759 EXPECT_EQ(OK
, callback3
.WaitForResult());
760 EXPECT_FALSE(info
.is_direct());
761 EXPECT_EQ("foopy3:7070", info
.proxy_server().ToURI());
763 // Proxy times should have been updated, so get them again.
764 EXPECT_LE(proxy_resolve_end_time
, info
.proxy_resolve_start_time());
765 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
766 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
767 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
768 proxy_resolve_start_time
= info
.proxy_resolve_start_time();
769 proxy_resolve_end_time
= info
.proxy_resolve_end_time();
771 // We fake another error. It should now try the third one.
772 TestCompletionCallback callback4
;
773 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
776 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
778 // We fake another error. At this point we have tried all of the
779 // proxy servers we thought were valid; next we try the proxy server
780 // that was in our bad proxies map (foopy1:8080).
781 TestCompletionCallback callback5
;
782 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback5
.callback(), NULL
,
785 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
787 // Fake another error, the last proxy is gone, the list should now be empty,
788 // so there is nothing left to try.
789 TestCompletionCallback callback6
;
790 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback6
.callback(), NULL
,
792 EXPECT_EQ(ERR_FAILED
, rv
);
793 EXPECT_FALSE(info
.is_direct());
794 EXPECT_TRUE(info
.is_empty());
796 // Proxy times should not have been modified by fallback.
797 EXPECT_EQ(proxy_resolve_start_time
, info
.proxy_resolve_start_time());
798 EXPECT_EQ(proxy_resolve_end_time
, info
.proxy_resolve_end_time());
800 // Look up proxies again
801 TestCompletionCallback callback7
;
802 rv
= service
.ResolveProxy(url
, &info
, callback7
.callback(), NULL
,
804 EXPECT_EQ(ERR_IO_PENDING
, rv
);
806 ASSERT_EQ(1u, resolver
->pending_requests().size());
807 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
809 // This time, the first 3 results have been found to be bad, but only the
810 // first proxy has been confirmed ...
811 resolver
->pending_requests()[0]->results()->UseNamedProxy(
812 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
813 resolver
->pending_requests()[0]->CompleteNow(OK
);
815 // ... therefore, we should see the second proxy first.
816 EXPECT_EQ(OK
, callback7
.WaitForResult());
817 EXPECT_FALSE(info
.is_direct());
818 EXPECT_EQ("foopy3:7070", info
.proxy_server().ToURI());
820 EXPECT_LE(proxy_resolve_end_time
, info
.proxy_resolve_start_time());
821 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
822 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
823 // TODO(nsylvain): Test that the proxy can be retried after the delay.
826 // This test is similar to ProxyFallback, but this time we have an explicit
827 // fallback choice to DIRECT.
828 TEST_F(ProxyServiceTest
, ProxyFallbackToDirect
) {
829 MockProxyConfigService
* config_service
=
830 new MockProxyConfigService("http://foopy/proxy.pac");
832 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
834 ProxyService
service(config_service
, resolver
, NULL
);
836 GURL
url("http://www.google.com/");
838 // Get the proxy information.
840 TestCompletionCallback callback1
;
841 int rv
= service
.ResolveProxy(
842 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
843 EXPECT_EQ(ERR_IO_PENDING
, rv
);
845 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
846 resolver
->pending_set_pac_script_request()->script_data()->url());
847 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
849 ASSERT_EQ(1u, resolver
->pending_requests().size());
850 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
852 // Set the result in proxy resolver.
853 resolver
->pending_requests()[0]->results()->UsePacString(
854 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
855 resolver
->pending_requests()[0]->CompleteNow(OK
);
857 // Get the first result.
858 EXPECT_EQ(OK
, callback1
.WaitForResult());
859 EXPECT_FALSE(info
.is_direct());
860 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
862 // Fake an error on the proxy.
863 TestCompletionCallback callback2
;
864 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
868 // Now we get back the second proxy.
869 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
871 // Fake an error on this proxy as well.
872 TestCompletionCallback callback3
;
873 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback3
.callback(), NULL
,
877 // Finally, we get back DIRECT.
878 EXPECT_TRUE(info
.is_direct());
880 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
881 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
882 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
884 // Now we tell the proxy service that even DIRECT failed.
885 TestCompletionCallback callback4
;
886 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
888 // There was nothing left to try after DIRECT, so we are out of
890 EXPECT_EQ(ERR_FAILED
, rv
);
893 TEST_F(ProxyServiceTest
, ProxyFallback_NewSettings
) {
894 // Test proxy failover when new settings are available.
896 MockProxyConfigService
* config_service
=
897 new MockProxyConfigService("http://foopy/proxy.pac");
899 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
901 ProxyService
service(config_service
, resolver
, NULL
);
903 GURL
url("http://www.google.com/");
905 // Get the proxy information.
907 TestCompletionCallback callback1
;
908 int rv
= service
.ResolveProxy(
909 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
912 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
913 resolver
->pending_set_pac_script_request()->script_data()->url());
914 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
916 ASSERT_EQ(1u, resolver
->pending_requests().size());
917 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
919 // Set the result in proxy resolver.
920 resolver
->pending_requests()[0]->results()->UseNamedProxy(
921 "foopy1:8080;foopy2:9090");
922 resolver
->pending_requests()[0]->CompleteNow(OK
);
924 // The first item is valid.
925 EXPECT_EQ(OK
, callback1
.WaitForResult());
926 EXPECT_FALSE(info
.is_direct());
927 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
929 // Fake an error on the proxy, and also a new configuration on the proxy.
930 config_service
->SetConfig(
931 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
933 TestCompletionCallback callback2
;
934 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
936 EXPECT_EQ(ERR_IO_PENDING
, rv
);
938 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
939 resolver
->pending_set_pac_script_request()->script_data()->url());
940 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
942 ASSERT_EQ(1u, resolver
->pending_requests().size());
943 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
945 resolver
->pending_requests()[0]->results()->UseNamedProxy(
946 "foopy1:8080;foopy2:9090");
947 resolver
->pending_requests()[0]->CompleteNow(OK
);
949 // The first proxy is still there since the configuration changed.
950 EXPECT_EQ(OK
, callback2
.WaitForResult());
951 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
953 // We fake another error. It should now ignore the first one.
954 TestCompletionCallback callback3
;
955 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback3
.callback(), NULL
,
958 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
960 // We simulate a new configuration.
961 config_service
->SetConfig(
962 ProxyConfig::CreateFromCustomPacURL(
963 GURL("http://foopy-new2/proxy.pac")));
965 // We fake another error. It should go back to the first proxy.
966 TestCompletionCallback callback4
;
967 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback4
.callback(), NULL
,
969 EXPECT_EQ(ERR_IO_PENDING
, rv
);
971 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
972 resolver
->pending_set_pac_script_request()->script_data()->url());
973 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
975 ASSERT_EQ(1u, resolver
->pending_requests().size());
976 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
978 resolver
->pending_requests()[0]->results()->UseNamedProxy(
979 "foopy1:8080;foopy2:9090");
980 resolver
->pending_requests()[0]->CompleteNow(OK
);
982 EXPECT_EQ(OK
, callback4
.WaitForResult());
983 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
985 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
986 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
987 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
990 TEST_F(ProxyServiceTest
, ProxyFallback_BadConfig
) {
991 // Test proxy failover when the configuration is bad.
993 MockProxyConfigService
* config_service
=
994 new MockProxyConfigService("http://foopy/proxy.pac");
996 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
998 ProxyService
service(config_service
, resolver
, NULL
);
1000 GURL
url("http://www.google.com/");
1002 // Get the proxy information.
1004 TestCompletionCallback callback1
;
1005 int rv
= service
.ResolveProxy(
1006 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
1007 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1009 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1010 resolver
->pending_set_pac_script_request()->script_data()->url());
1011 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1012 ASSERT_EQ(1u, resolver
->pending_requests().size());
1013 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1015 resolver
->pending_requests()[0]->results()->UseNamedProxy(
1016 "foopy1:8080;foopy2:9090");
1017 resolver
->pending_requests()[0]->CompleteNow(OK
);
1019 // The first item is valid.
1020 EXPECT_EQ(OK
, callback1
.WaitForResult());
1021 EXPECT_FALSE(info
.is_direct());
1022 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1024 // Fake a proxy error.
1025 TestCompletionCallback callback2
;
1026 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
1030 // The first proxy is ignored, and the second one is selected.
1031 EXPECT_FALSE(info
.is_direct());
1032 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
1034 // Fake a PAC failure.
1036 TestCompletionCallback callback3
;
1037 rv
= service
.ResolveProxy(
1038 url
, &info2
, callback3
.callback(), NULL
, BoundNetLog());
1039 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1041 ASSERT_EQ(1u, resolver
->pending_requests().size());
1042 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1044 // This simulates a javascript runtime error in the PAC script.
1045 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
1047 // Although the resolver failed, the ProxyService will implicitly fall-back
1048 // to a DIRECT connection.
1049 EXPECT_EQ(OK
, callback3
.WaitForResult());
1050 EXPECT_TRUE(info2
.is_direct());
1051 EXPECT_FALSE(info2
.is_empty());
1053 // The PAC script will work properly next time and successfully return a
1054 // proxy list. Since we have not marked the configuration as bad, it should
1055 // "just work" the next time we call it.
1057 TestCompletionCallback callback4
;
1058 rv
= service
.ReconsiderProxyAfterError(url
, &info3
, callback4
.callback(),
1059 NULL
, BoundNetLog());
1060 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1062 ASSERT_EQ(1u, resolver
->pending_requests().size());
1063 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1065 resolver
->pending_requests()[0]->results()->UseNamedProxy(
1066 "foopy1:8080;foopy2:9090");
1067 resolver
->pending_requests()[0]->CompleteNow(OK
);
1069 // The first proxy is not there since the it was added to the bad proxies
1070 // list by the earlier ReconsiderProxyAfterError().
1071 EXPECT_EQ(OK
, callback4
.WaitForResult());
1072 EXPECT_FALSE(info3
.is_direct());
1073 EXPECT_EQ("foopy1:8080", info3
.proxy_server().ToURI());
1075 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
1076 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
1077 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
1080 TEST_F(ProxyServiceTest
, ProxyFallback_BadConfigMandatory
) {
1081 // Test proxy failover when the configuration is bad.
1084 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1086 config
.set_pac_mandatory(true);
1087 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1089 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
1091 ProxyService
service(config_service
, resolver
, NULL
);
1093 GURL
url("http://www.google.com/");
1095 // Get the proxy information.
1097 TestCompletionCallback callback1
;
1098 int rv
= service
.ResolveProxy(
1099 url
, &info
, callback1
.callback(), NULL
, BoundNetLog());
1100 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1102 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1103 resolver
->pending_set_pac_script_request()->script_data()->url());
1104 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1105 ASSERT_EQ(1u, resolver
->pending_requests().size());
1106 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1108 resolver
->pending_requests()[0]->results()->UseNamedProxy(
1109 "foopy1:8080;foopy2:9090");
1110 resolver
->pending_requests()[0]->CompleteNow(OK
);
1112 // The first item is valid.
1113 EXPECT_EQ(OK
, callback1
.WaitForResult());
1114 EXPECT_FALSE(info
.is_direct());
1115 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1117 // Fake a proxy error.
1118 TestCompletionCallback callback2
;
1119 rv
= service
.ReconsiderProxyAfterError(url
, &info
, callback2
.callback(), NULL
,
1123 // The first proxy is ignored, and the second one is selected.
1124 EXPECT_FALSE(info
.is_direct());
1125 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
1127 // Fake a PAC failure.
1129 TestCompletionCallback callback3
;
1130 rv
= service
.ResolveProxy(
1131 url
, &info2
, callback3
.callback(), NULL
, BoundNetLog());
1132 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1134 ASSERT_EQ(1u, resolver
->pending_requests().size());
1135 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1137 // This simulates a javascript runtime error in the PAC script.
1138 resolver
->pending_requests()[0]->CompleteNow(ERR_FAILED
);
1140 // Although the resolver failed, the ProxyService will NOT fall-back
1141 // to a DIRECT connection as it is configured as mandatory.
1142 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
1143 callback3
.WaitForResult());
1144 EXPECT_FALSE(info2
.is_direct());
1145 EXPECT_TRUE(info2
.is_empty());
1147 // The PAC script will work properly next time and successfully return a
1148 // proxy list. Since we have not marked the configuration as bad, it should
1149 // "just work" the next time we call it.
1151 TestCompletionCallback callback4
;
1152 rv
= service
.ReconsiderProxyAfterError(url
, &info3
, callback4
.callback(),
1153 NULL
, BoundNetLog());
1154 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1156 ASSERT_EQ(1u, resolver
->pending_requests().size());
1157 EXPECT_EQ(url
, resolver
->pending_requests()[0]->url());
1159 resolver
->pending_requests()[0]->results()->UseNamedProxy(
1160 "foopy1:8080;foopy2:9090");
1161 resolver
->pending_requests()[0]->CompleteNow(OK
);
1163 // The first proxy is not there since the it was added to the bad proxies
1164 // list by the earlier ReconsiderProxyAfterError().
1165 EXPECT_EQ(OK
, callback4
.WaitForResult());
1166 EXPECT_FALSE(info3
.is_direct());
1167 EXPECT_EQ("foopy1:8080", info3
.proxy_server().ToURI());
1170 TEST_F(ProxyServiceTest
, ProxyBypassList
) {
1171 // Test that the proxy bypass rules are consulted.
1173 TestCompletionCallback callback
[2];
1176 config
.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1177 config
.set_auto_detect(false);
1178 config
.proxy_rules().bypass_rules
.ParseFromString("*.org");
1180 ProxyService
service(
1181 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1184 GURL
url1("http://www.webkit.org");
1185 GURL
url2("http://www.webkit.com");
1187 // Request for a .org domain should bypass proxy.
1188 rv
= service
.ResolveProxy(
1189 url1
, &info
[0], callback
[0].callback(), NULL
, BoundNetLog());
1191 EXPECT_TRUE(info
[0].is_direct());
1193 // Request for a .com domain hits the proxy.
1194 rv
= service
.ResolveProxy(
1195 url2
, &info
[1], callback
[1].callback(), NULL
, BoundNetLog());
1197 EXPECT_EQ("foopy1:8080", info
[1].proxy_server().ToURI());
1201 TEST_F(ProxyServiceTest
, PerProtocolProxyTests
) {
1203 config
.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1204 config
.set_auto_detect(false);
1206 ProxyService
service(
1207 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1208 GURL
test_url("http://www.msn.com");
1210 TestCompletionCallback callback
;
1211 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1214 EXPECT_FALSE(info
.is_direct());
1215 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1218 ProxyService
service(
1219 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1220 GURL
test_url("ftp://ftp.google.com");
1222 TestCompletionCallback callback
;
1223 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1226 EXPECT_TRUE(info
.is_direct());
1227 EXPECT_EQ("direct://", info
.proxy_server().ToURI());
1230 ProxyService
service(
1231 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1232 GURL
test_url("https://webbranch.techcu.com");
1234 TestCompletionCallback callback
;
1235 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1238 EXPECT_FALSE(info
.is_direct());
1239 EXPECT_EQ("foopy2:8080", info
.proxy_server().ToURI());
1242 config
.proxy_rules().ParseFromString("foopy1:8080");
1243 ProxyService
service(
1244 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1245 GURL
test_url("http://www.microsoft.com");
1247 TestCompletionCallback callback
;
1248 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1251 EXPECT_FALSE(info
.is_direct());
1252 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1256 TEST_F(ProxyServiceTest
, ProxyConfigSourcePropagates
) {
1257 // Test that the proxy config source is set correctly when resolving proxies
1258 // using manual proxy rules. Namely, the config source should only be set if
1259 // any of the rules were applied.
1262 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1263 config
.proxy_rules().ParseFromString("https=foopy2:8080");
1264 ProxyService
service(
1265 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1266 GURL
test_url("http://www.google.com");
1268 TestCompletionCallback callback
;
1269 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1272 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1273 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1277 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1278 config
.proxy_rules().ParseFromString("https=foopy2:8080");
1279 ProxyService
service(
1280 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1281 GURL
test_url("https://www.google.com");
1283 TestCompletionCallback callback
;
1284 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1287 // Used the HTTPS proxy. So source should be TEST.
1288 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1292 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1293 ProxyService
service(
1294 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1295 GURL
test_url("http://www.google.com");
1297 TestCompletionCallback callback
;
1298 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1301 // ProxyConfig is empty. Source should still be TEST.
1302 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1306 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1307 // fall back to the SOCKS proxy.
1308 TEST_F(ProxyServiceTest
, DefaultProxyFallbackToSOCKS
) {
1310 config
.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1311 config
.set_auto_detect(false);
1312 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME
,
1313 config
.proxy_rules().type
);
1316 ProxyService
service(
1317 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1318 GURL
test_url("http://www.msn.com");
1320 TestCompletionCallback callback
;
1321 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1324 EXPECT_FALSE(info
.is_direct());
1325 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1328 ProxyService
service(
1329 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1330 GURL
test_url("ftp://ftp.google.com");
1332 TestCompletionCallback callback
;
1333 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1336 EXPECT_FALSE(info
.is_direct());
1337 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1340 ProxyService
service(
1341 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1342 GURL
test_url("https://webbranch.techcu.com");
1344 TestCompletionCallback callback
;
1345 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1348 EXPECT_FALSE(info
.is_direct());
1349 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1352 ProxyService
service(
1353 new MockProxyConfigService(config
), new MockAsyncProxyResolver
, NULL
);
1354 GURL
test_url("unknown://www.microsoft.com");
1356 TestCompletionCallback callback
;
1357 int rv
= service
.ResolveProxy(test_url
, &info
, callback
.callback(), NULL
,
1360 EXPECT_FALSE(info
.is_direct());
1361 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1365 // Test cancellation of an in-progress request.
1366 TEST_F(ProxyServiceTest
, CancelInProgressRequest
) {
1367 MockProxyConfigService
* config_service
=
1368 new MockProxyConfigService("http://foopy/proxy.pac");
1370 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
1372 ProxyService
service(config_service
, resolver
, NULL
);
1374 // Start 3 requests.
1377 TestCompletionCallback callback1
;
1378 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1379 callback1
.callback(), NULL
, BoundNetLog());
1380 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1382 // Nothing has been sent to the proxy resolver yet, since the proxy
1383 // resolver has not been configured yet.
1384 ASSERT_EQ(0u, resolver
->pending_requests().size());
1386 // Successfully initialize the PAC script.
1387 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1388 resolver
->pending_set_pac_script_request()->script_data()->url());
1389 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1391 ASSERT_EQ(1u, resolver
->pending_requests().size());
1392 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1395 TestCompletionCallback callback2
;
1396 ProxyService::PacRequest
* request2
;
1397 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1398 callback2
.callback(), &request2
, BoundNetLog());
1399 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1400 ASSERT_EQ(2u, resolver
->pending_requests().size());
1401 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1404 TestCompletionCallback callback3
;
1405 rv
= service
.ResolveProxy(GURL("http://request3"), &info3
,
1406 callback3
.callback(), NULL
, BoundNetLog());
1407 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1408 ASSERT_EQ(3u, resolver
->pending_requests().size());
1409 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[2]->url());
1411 // Cancel the second request
1412 service
.CancelPacRequest(request2
);
1414 ASSERT_EQ(2u, resolver
->pending_requests().size());
1415 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1416 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[1]->url());
1418 // Complete the two un-cancelled requests.
1419 // We complete the last one first, just to mix it up a bit.
1420 resolver
->pending_requests()[1]->results()->UseNamedProxy("request3:80");
1421 resolver
->pending_requests()[1]->CompleteNow(OK
);
1423 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1424 resolver
->pending_requests()[0]->CompleteNow(OK
);
1426 // Complete and verify that requests ran as expected.
1427 EXPECT_EQ(OK
, callback1
.WaitForResult());
1428 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1430 EXPECT_FALSE(callback2
.have_result()); // Cancelled.
1431 ASSERT_EQ(1u, resolver
->cancelled_requests().size());
1432 EXPECT_EQ(GURL("http://request2"), resolver
->cancelled_requests()[0]->url());
1434 EXPECT_EQ(OK
, callback3
.WaitForResult());
1435 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1438 // Test the initial PAC download for resolver that expects bytes.
1439 TEST_F(ProxyServiceTest
, InitialPACScriptDownload
) {
1440 MockProxyConfigService
* config_service
=
1441 new MockProxyConfigService("http://foopy/proxy.pac");
1443 MockAsyncProxyResolverExpectsBytes
* resolver
=
1444 new MockAsyncProxyResolverExpectsBytes
;
1446 ProxyService
service(config_service
, resolver
, NULL
);
1448 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1449 service
.SetProxyScriptFetchers(fetcher
,
1450 new DoNothingDhcpProxyScriptFetcher());
1452 // Start 3 requests.
1455 TestCompletionCallback callback1
;
1456 ProxyService::PacRequest
* request1
;
1457 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1458 callback1
.callback(), &request1
, BoundNetLog());
1459 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1461 // The first request should have triggered download of PAC script.
1462 EXPECT_TRUE(fetcher
->has_pending_request());
1463 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1466 TestCompletionCallback callback2
;
1467 ProxyService::PacRequest
* request2
;
1468 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1469 callback2
.callback(), &request2
, BoundNetLog());
1470 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1473 TestCompletionCallback callback3
;
1474 ProxyService::PacRequest
* request3
;
1475 rv
= service
.ResolveProxy(GURL("http://request3"), &info3
,
1476 callback3
.callback(), &request3
, BoundNetLog());
1477 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1479 // Nothing has been sent to the resolver yet.
1480 EXPECT_TRUE(resolver
->pending_requests().empty());
1482 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT
,
1483 service
.GetLoadState(request1
));
1484 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT
,
1485 service
.GetLoadState(request2
));
1486 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT
,
1487 service
.GetLoadState(request3
));
1489 // At this point the ProxyService should be waiting for the
1490 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1491 // PAC script download completion.
1492 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1494 // Now that the PAC script is downloaded, it will have been sent to the proxy
1496 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1497 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1498 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1500 ASSERT_EQ(3u, resolver
->pending_requests().size());
1501 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1502 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1503 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[2]->url());
1505 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request1
));
1506 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request2
));
1507 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request3
));
1509 // Complete all the requests (in some order).
1510 // Note that as we complete requests, they shift up in |pending_requests()|.
1512 resolver
->pending_requests()[2]->results()->UseNamedProxy("request3:80");
1513 resolver
->pending_requests()[2]->CompleteNow(OK
);
1515 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1516 resolver
->pending_requests()[0]->CompleteNow(OK
);
1518 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1519 resolver
->pending_requests()[0]->CompleteNow(OK
);
1521 // Complete and verify that requests ran as expected.
1522 EXPECT_EQ(OK
, callback1
.WaitForResult());
1523 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1524 EXPECT_FALSE(info1
.proxy_resolve_start_time().is_null());
1525 EXPECT_FALSE(info1
.proxy_resolve_end_time().is_null());
1526 EXPECT_LE(info1
.proxy_resolve_start_time(), info1
.proxy_resolve_end_time());
1528 EXPECT_EQ(OK
, callback2
.WaitForResult());
1529 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1530 EXPECT_FALSE(info2
.proxy_resolve_start_time().is_null());
1531 EXPECT_FALSE(info2
.proxy_resolve_end_time().is_null());
1532 EXPECT_LE(info2
.proxy_resolve_start_time(), info2
.proxy_resolve_end_time());
1534 EXPECT_EQ(OK
, callback3
.WaitForResult());
1535 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1536 EXPECT_FALSE(info3
.proxy_resolve_start_time().is_null());
1537 EXPECT_FALSE(info3
.proxy_resolve_end_time().is_null());
1538 EXPECT_LE(info3
.proxy_resolve_start_time(), info3
.proxy_resolve_end_time());
1541 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1542 TEST_F(ProxyServiceTest
, ChangeScriptFetcherWhilePACDownloadInProgress
) {
1543 MockProxyConfigService
* config_service
=
1544 new MockProxyConfigService("http://foopy/proxy.pac");
1546 MockAsyncProxyResolverExpectsBytes
* resolver
=
1547 new MockAsyncProxyResolverExpectsBytes
;
1549 ProxyService
service(config_service
, resolver
, NULL
);
1551 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1552 service
.SetProxyScriptFetchers(fetcher
,
1553 new DoNothingDhcpProxyScriptFetcher());
1555 // Start 2 requests.
1558 TestCompletionCallback callback1
;
1559 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1560 callback1
.callback(), NULL
, BoundNetLog());
1561 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1563 // The first request should have triggered download of PAC script.
1564 EXPECT_TRUE(fetcher
->has_pending_request());
1565 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1568 TestCompletionCallback callback2
;
1569 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1570 callback2
.callback(), NULL
, BoundNetLog());
1571 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1573 // At this point the ProxyService should be waiting for the
1574 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1575 // PAC script download completion.
1577 // We now change out the ProxyService's script fetcher. We should restart
1578 // the initialization with the new fetcher.
1580 fetcher
= new MockProxyScriptFetcher
;
1581 service
.SetProxyScriptFetchers(fetcher
,
1582 new DoNothingDhcpProxyScriptFetcher());
1584 // Nothing has been sent to the resolver yet.
1585 EXPECT_TRUE(resolver
->pending_requests().empty());
1587 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1589 // Now that the PAC script is downloaded, it will have been sent to the proxy
1591 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1592 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1593 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1595 ASSERT_EQ(2u, resolver
->pending_requests().size());
1596 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1597 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1600 // Test cancellation of a request, while the PAC script is being fetched.
1601 TEST_F(ProxyServiceTest
, CancelWhilePACFetching
) {
1602 MockProxyConfigService
* config_service
=
1603 new MockProxyConfigService("http://foopy/proxy.pac");
1605 MockAsyncProxyResolverExpectsBytes
* resolver
=
1606 new MockAsyncProxyResolverExpectsBytes
;
1608 ProxyService
service(config_service
, resolver
, NULL
);
1610 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1611 service
.SetProxyScriptFetchers(fetcher
,
1612 new DoNothingDhcpProxyScriptFetcher());
1614 // Start 3 requests.
1616 TestCompletionCallback callback1
;
1617 ProxyService::PacRequest
* request1
;
1618 CapturingBoundNetLog log1
;
1619 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1620 callback1
.callback(), &request1
, log1
.bound());
1621 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1623 // The first request should have triggered download of PAC script.
1624 EXPECT_TRUE(fetcher
->has_pending_request());
1625 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1628 TestCompletionCallback callback2
;
1629 ProxyService::PacRequest
* request2
;
1630 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1631 callback2
.callback(), &request2
, BoundNetLog());
1632 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1635 TestCompletionCallback callback3
;
1636 rv
= service
.ResolveProxy(GURL("http://request3"), &info3
,
1637 callback3
.callback(), NULL
, BoundNetLog());
1638 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1640 // Nothing has been sent to the resolver yet.
1641 EXPECT_TRUE(resolver
->pending_requests().empty());
1643 // Cancel the first 2 requests.
1644 service
.CancelPacRequest(request1
);
1645 service
.CancelPacRequest(request2
);
1647 // At this point the ProxyService should be waiting for the
1648 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1649 // PAC script download completion.
1650 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1652 // Now that the PAC script is downloaded, it will have been sent to the
1654 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1655 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1656 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1658 ASSERT_EQ(1u, resolver
->pending_requests().size());
1659 EXPECT_EQ(GURL("http://request3"), resolver
->pending_requests()[0]->url());
1661 // Complete all the requests.
1662 resolver
->pending_requests()[0]->results()->UseNamedProxy("request3:80");
1663 resolver
->pending_requests()[0]->CompleteNow(OK
);
1665 EXPECT_EQ(OK
, callback3
.WaitForResult());
1666 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1668 EXPECT_TRUE(resolver
->cancelled_requests().empty());
1670 EXPECT_FALSE(callback1
.have_result()); // Cancelled.
1671 EXPECT_FALSE(callback2
.have_result()); // Cancelled.
1673 CapturingNetLog::CapturedEntryList entries1
;
1674 log1
.GetEntries(&entries1
);
1676 // Check the NetLog for request 1 (which was cancelled) got filled properly.
1677 EXPECT_EQ(4u, entries1
.size());
1678 EXPECT_TRUE(LogContainsBeginEvent(
1679 entries1
, 0, NetLog::TYPE_PROXY_SERVICE
));
1680 EXPECT_TRUE(LogContainsBeginEvent(
1681 entries1
, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
1682 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1683 // the cancellation occured.
1684 EXPECT_TRUE(LogContainsEvent(
1685 entries1
, 2, NetLog::TYPE_CANCELLED
, NetLog::PHASE_NONE
));
1686 EXPECT_TRUE(LogContainsEndEvent(
1687 entries1
, 3, NetLog::TYPE_PROXY_SERVICE
));
1690 // Test that if auto-detect fails, we fall-back to the custom pac.
1691 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomPac
) {
1693 config
.set_auto_detect(true);
1694 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1695 config
.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1697 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1698 MockAsyncProxyResolverExpectsBytes
* resolver
=
1699 new MockAsyncProxyResolverExpectsBytes
;
1700 ProxyService
service(config_service
, resolver
, NULL
);
1702 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1703 service
.SetProxyScriptFetchers(fetcher
,
1704 new DoNothingDhcpProxyScriptFetcher());
1706 // Start 2 requests.
1709 TestCompletionCallback callback1
;
1710 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1711 callback1
.callback(), NULL
, BoundNetLog());
1712 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1715 TestCompletionCallback callback2
;
1716 ProxyService::PacRequest
* request2
;
1717 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1718 callback2
.callback(), &request2
, BoundNetLog());
1719 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1721 // Check that nothing has been sent to the proxy resolver yet.
1722 ASSERT_EQ(0u, resolver
->pending_requests().size());
1724 // It should be trying to auto-detect first -- FAIL the autodetect during
1725 // the script download.
1726 EXPECT_TRUE(fetcher
->has_pending_request());
1727 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1728 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
1730 // Next it should be trying the custom PAC url.
1731 EXPECT_TRUE(fetcher
->has_pending_request());
1732 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1733 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1735 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1736 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1737 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1739 // Now finally, the pending requests should have been sent to the resolver
1740 // (which was initialized with custom PAC script).
1742 ASSERT_EQ(2u, resolver
->pending_requests().size());
1743 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1744 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1746 // Complete the pending requests.
1747 resolver
->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1748 resolver
->pending_requests()[1]->CompleteNow(OK
);
1749 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1750 resolver
->pending_requests()[0]->CompleteNow(OK
);
1752 // Verify that requests ran as expected.
1753 EXPECT_EQ(OK
, callback1
.WaitForResult());
1754 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1755 EXPECT_FALSE(info1
.proxy_resolve_start_time().is_null());
1756 EXPECT_FALSE(info1
.proxy_resolve_end_time().is_null());
1757 EXPECT_LE(info1
.proxy_resolve_start_time(), info1
.proxy_resolve_end_time());
1759 EXPECT_EQ(OK
, callback2
.WaitForResult());
1760 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1761 EXPECT_FALSE(info2
.proxy_resolve_start_time().is_null());
1762 EXPECT_FALSE(info2
.proxy_resolve_end_time().is_null());
1763 EXPECT_LE(info2
.proxy_resolve_start_time(), info2
.proxy_resolve_end_time());
1766 // This is the same test as FallbackFromAutodetectToCustomPac, except
1767 // the auto-detect script fails parsing rather than downloading.
1768 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomPac2
) {
1770 config
.set_auto_detect(true);
1771 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1772 config
.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1774 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1775 MockAsyncProxyResolverExpectsBytes
* resolver
=
1776 new MockAsyncProxyResolverExpectsBytes
;
1777 ProxyService
service(config_service
, resolver
, NULL
);
1779 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1780 service
.SetProxyScriptFetchers(fetcher
,
1781 new DoNothingDhcpProxyScriptFetcher());
1783 // Start 2 requests.
1786 TestCompletionCallback callback1
;
1787 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1788 callback1
.callback(), NULL
, BoundNetLog());
1789 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1792 TestCompletionCallback callback2
;
1793 ProxyService::PacRequest
* request2
;
1794 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1795 callback2
.callback(), &request2
, BoundNetLog());
1796 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1798 // Check that nothing has been sent to the proxy resolver yet.
1799 ASSERT_EQ(0u, resolver
->pending_requests().size());
1801 // It should be trying to auto-detect first -- succeed the download.
1802 EXPECT_TRUE(fetcher
->has_pending_request());
1803 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1804 fetcher
->NotifyFetchCompletion(OK
, "invalid-script-contents");
1806 // The script contents passed failed basic verification step (since didn't
1807 // contain token FindProxyForURL), so it was never passed to the resolver.
1809 // Next it should be trying the custom PAC url.
1810 EXPECT_TRUE(fetcher
->has_pending_request());
1811 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1812 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1814 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1815 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1816 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1818 // Now finally, the pending requests should have been sent to the resolver
1819 // (which was initialized with custom PAC script).
1821 ASSERT_EQ(2u, resolver
->pending_requests().size());
1822 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
1823 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[1]->url());
1825 // Complete the pending requests.
1826 resolver
->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1827 resolver
->pending_requests()[1]->CompleteNow(OK
);
1828 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1829 resolver
->pending_requests()[0]->CompleteNow(OK
);
1831 // Verify that requests ran as expected.
1832 EXPECT_EQ(OK
, callback1
.WaitForResult());
1833 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1835 EXPECT_EQ(OK
, callback2
.WaitForResult());
1836 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1839 // Test that if all of auto-detect, a custom PAC script, and manual settings
1840 // are given, then we will try them in that order.
1841 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomToManual
) {
1843 config
.set_auto_detect(true);
1844 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1845 config
.proxy_rules().ParseFromString("http=foopy:80");
1847 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1848 MockAsyncProxyResolverExpectsBytes
* resolver
=
1849 new MockAsyncProxyResolverExpectsBytes
;
1850 ProxyService
service(config_service
, resolver
, NULL
);
1852 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1853 service
.SetProxyScriptFetchers(fetcher
,
1854 new DoNothingDhcpProxyScriptFetcher());
1856 // Start 2 requests.
1859 TestCompletionCallback callback1
;
1860 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
1861 callback1
.callback(), NULL
, BoundNetLog());
1862 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1865 TestCompletionCallback callback2
;
1866 ProxyService::PacRequest
* request2
;
1867 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
1868 callback2
.callback(), &request2
, BoundNetLog());
1869 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1871 // Check that nothing has been sent to the proxy resolver yet.
1872 ASSERT_EQ(0u, resolver
->pending_requests().size());
1874 // It should be trying to auto-detect first -- fail the download.
1875 EXPECT_TRUE(fetcher
->has_pending_request());
1876 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1877 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
1879 // Next it should be trying the custom PAC url -- fail the download.
1880 EXPECT_TRUE(fetcher
->has_pending_request());
1881 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1882 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
1884 // Since we never managed to initialize a ProxyResolver, nothing should have
1886 ASSERT_EQ(0u, resolver
->pending_requests().size());
1888 // Verify that requests ran as expected -- they should have fallen back to
1889 // the manual proxy configuration for HTTP urls.
1890 EXPECT_EQ(OK
, callback1
.WaitForResult());
1891 EXPECT_EQ("foopy:80", info1
.proxy_server().ToURI());
1893 EXPECT_EQ(OK
, callback2
.WaitForResult());
1894 EXPECT_EQ("foopy:80", info2
.proxy_server().ToURI());
1897 // Test that the bypass rules are NOT applied when using autodetect.
1898 TEST_F(ProxyServiceTest
, BypassDoesntApplyToPac
) {
1900 config
.set_auto_detect(true);
1901 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1902 config
.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
1903 config
.proxy_rules().bypass_rules
.ParseFromString("www.google.com");
1905 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1906 MockAsyncProxyResolverExpectsBytes
* resolver
=
1907 new MockAsyncProxyResolverExpectsBytes
;
1908 ProxyService
service(config_service
, resolver
, NULL
);
1910 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1911 service
.SetProxyScriptFetchers(fetcher
,
1912 new DoNothingDhcpProxyScriptFetcher());
1914 // Start 1 requests.
1917 TestCompletionCallback callback1
;
1918 int rv
= service
.ResolveProxy(
1919 GURL("http://www.google.com"), &info1
, callback1
.callback(), NULL
,
1921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1923 // Check that nothing has been sent to the proxy resolver yet.
1924 ASSERT_EQ(0u, resolver
->pending_requests().size());
1926 // It should be trying to auto-detect first -- succeed the download.
1927 EXPECT_TRUE(fetcher
->has_pending_request());
1928 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1929 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1931 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1932 resolver
->pending_set_pac_script_request()->script_data()->utf16());
1933 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
1935 ASSERT_EQ(1u, resolver
->pending_requests().size());
1936 EXPECT_EQ(GURL("http://www.google.com"),
1937 resolver
->pending_requests()[0]->url());
1939 // Complete the pending request.
1940 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1941 resolver
->pending_requests()[0]->CompleteNow(OK
);
1943 // Verify that request ran as expected.
1944 EXPECT_EQ(OK
, callback1
.WaitForResult());
1945 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1947 // Start another request, it should pickup the bypass item.
1949 TestCompletionCallback callback2
;
1950 rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info2
,
1951 callback2
.callback(), NULL
, BoundNetLog());
1952 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1954 ASSERT_EQ(1u, resolver
->pending_requests().size());
1955 EXPECT_EQ(GURL("http://www.google.com"),
1956 resolver
->pending_requests()[0]->url());
1958 // Complete the pending request.
1959 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1960 resolver
->pending_requests()[0]->CompleteNow(OK
);
1962 EXPECT_EQ(OK
, callback2
.WaitForResult());
1963 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1966 // Delete the ProxyService while InitProxyResolver has an outstanding
1967 // request to the script fetcher. When run under valgrind, should not
1968 // have any memory errors (used to be that the ProxyScriptFetcher was
1969 // being deleted prior to the InitProxyResolver).
1970 TEST_F(ProxyServiceTest
, DeleteWhileInitProxyResolverHasOutstandingFetch
) {
1971 ProxyConfig config
=
1972 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
1974 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1975 MockAsyncProxyResolverExpectsBytes
* resolver
=
1976 new MockAsyncProxyResolverExpectsBytes
;
1977 ProxyService
service(config_service
, resolver
, NULL
);
1979 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1980 service
.SetProxyScriptFetchers(fetcher
,
1981 new DoNothingDhcpProxyScriptFetcher());
1986 TestCompletionCallback callback1
;
1987 int rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info1
,
1988 callback1
.callback(), NULL
, BoundNetLog());
1989 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1991 // Check that nothing has been sent to the proxy resolver yet.
1992 ASSERT_EQ(0u, resolver
->pending_requests().size());
1994 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
1995 // and be waiting on that to complete.
1996 EXPECT_TRUE(fetcher
->has_pending_request());
1997 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2000 // Delete the ProxyService while InitProxyResolver has an outstanding
2001 // request to the proxy resolver. When run under valgrind, should not
2002 // have any memory errors (used to be that the ProxyResolver was
2003 // being deleted prior to the InitProxyResolver).
2004 TEST_F(ProxyServiceTest
, DeleteWhileInitProxyResolverHasOutstandingSet
) {
2005 MockProxyConfigService
* config_service
=
2006 new MockProxyConfigService("http://foopy/proxy.pac");
2008 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
2010 ProxyService
service(config_service
, resolver
, NULL
);
2012 GURL
url("http://www.google.com/");
2015 TestCompletionCallback callback
;
2016 int rv
= service
.ResolveProxy(
2017 url
, &info
, callback
.callback(), NULL
, BoundNetLog());
2018 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2020 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2021 resolver
->pending_set_pac_script_request()->script_data()->url());
2024 TEST_F(ProxyServiceTest
, ResetProxyConfigService
) {
2025 ProxyConfig config1
;
2026 config1
.proxy_rules().ParseFromString("foopy1:8080");
2027 config1
.set_auto_detect(false);
2028 ProxyService
service(
2029 new MockProxyConfigService(config1
),
2030 new MockAsyncProxyResolverExpectsBytes
, NULL
);
2033 TestCompletionCallback callback1
;
2034 int rv
= service
.ResolveProxy(GURL("http://request1"), &info
,
2035 callback1
.callback(), NULL
, BoundNetLog());
2037 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
2039 ProxyConfig config2
;
2040 config2
.proxy_rules().ParseFromString("foopy2:8080");
2041 config2
.set_auto_detect(false);
2042 service
.ResetConfigService(new MockProxyConfigService(config2
));
2043 TestCompletionCallback callback2
;
2044 rv
= service
.ResolveProxy(GURL("http://request2"), &info
,
2045 callback2
.callback(), NULL
, BoundNetLog());
2047 EXPECT_EQ("foopy2:8080", info
.proxy_server().ToURI());
2050 // Test that when going from a configuration that required PAC to one
2051 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2052 TEST_F(ProxyServiceTest
, UpdateConfigFromPACToDirect
) {
2053 ProxyConfig config
= ProxyConfig::CreateAutoDetect();
2055 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
2056 MockAsyncProxyResolver
* resolver
= new MockAsyncProxyResolver
;
2057 ProxyService
service(config_service
, resolver
, NULL
);
2062 TestCompletionCallback callback1
;
2063 int rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info1
,
2064 callback1
.callback(), NULL
, BoundNetLog());
2065 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2067 // Check that nothing has been sent to the proxy resolver yet.
2068 ASSERT_EQ(0u, resolver
->pending_requests().size());
2070 // Successfully set the autodetect script.
2071 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT
,
2072 resolver
->pending_set_pac_script_request()->script_data()->type());
2073 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2075 // Complete the pending request.
2076 ASSERT_EQ(1u, resolver
->pending_requests().size());
2077 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2078 resolver
->pending_requests()[0]->CompleteNow(OK
);
2080 // Verify that request ran as expected.
2081 EXPECT_EQ(OK
, callback1
.WaitForResult());
2082 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2084 // Force the ProxyService to pull down a new proxy configuration.
2085 // (Even though the configuration isn't old/bad).
2087 // This new configuration no longer has auto_detect set, so
2088 // requests should complete synchronously now as direct-connect.
2089 config_service
->SetConfig(ProxyConfig::CreateDirect());
2091 // Start another request -- the effective configuration has changed.
2093 TestCompletionCallback callback2
;
2094 rv
= service
.ResolveProxy(GURL("http://www.google.com"), &info2
,
2095 callback2
.callback(), NULL
, BoundNetLog());
2098 EXPECT_TRUE(info2
.is_direct());
2101 TEST_F(ProxyServiceTest
, NetworkChangeTriggersPacRefetch
) {
2102 MockProxyConfigService
* config_service
=
2103 new MockProxyConfigService("http://foopy/proxy.pac");
2105 MockAsyncProxyResolverExpectsBytes
* resolver
=
2106 new MockAsyncProxyResolverExpectsBytes
;
2108 CapturingNetLog log
;
2110 ProxyService
service(config_service
, resolver
, &log
);
2112 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2113 service
.SetProxyScriptFetchers(fetcher
,
2114 new DoNothingDhcpProxyScriptFetcher());
2116 // Disable the "wait after IP address changes" hack, so this unit-test can
2117 // complete quickly.
2118 service
.set_stall_proxy_auto_config_delay(base::TimeDelta());
2123 TestCompletionCallback callback1
;
2124 int rv
= service
.ResolveProxy(GURL("http://request1"), &info1
,
2125 callback1
.callback(), NULL
, BoundNetLog());
2126 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2128 // The first request should have triggered initial download of PAC script.
2129 EXPECT_TRUE(fetcher
->has_pending_request());
2130 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2132 // Nothing has been sent to the resolver yet.
2133 EXPECT_TRUE(resolver
->pending_requests().empty());
2135 // At this point the ProxyService should be waiting for the
2136 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2137 // PAC script download completion.
2138 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2140 // Now that the PAC script is downloaded, the request will have been sent to
2141 // the proxy resolver.
2142 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2143 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2144 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2146 ASSERT_EQ(1u, resolver
->pending_requests().size());
2147 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2149 // Complete the pending request.
2150 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2151 resolver
->pending_requests()[0]->CompleteNow(OK
);
2153 // Wait for completion callback, and verify that the request ran as expected.
2154 EXPECT_EQ(OK
, callback1
.WaitForResult());
2155 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2157 // Now simluate a change in the network. The ProxyConfigService is still
2158 // going to return the same PAC URL as before, but this URL needs to be
2159 // refetched on the new network.
2160 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2161 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2163 // Start a second request.
2165 TestCompletionCallback callback2
;
2166 rv
= service
.ResolveProxy(GURL("http://request2"), &info2
,
2167 callback2
.callback(), NULL
, BoundNetLog());
2168 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2170 // This second request should have triggered the re-download of the PAC
2171 // script (since we marked the network as having changed).
2172 EXPECT_TRUE(fetcher
->has_pending_request());
2173 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2175 // Nothing has been sent to the resolver yet.
2176 EXPECT_TRUE(resolver
->pending_requests().empty());
2178 // Simulate the PAC script fetch as having completed (this time with
2180 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript2
);
2182 // Now that the PAC script is downloaded, the second request will have been
2183 // sent to the proxy resolver.
2184 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2
),
2185 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2186 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2188 ASSERT_EQ(1u, resolver
->pending_requests().size());
2189 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2191 // Complete the pending second request.
2192 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2193 resolver
->pending_requests()[0]->CompleteNow(OK
);
2195 // Wait for completion callback, and verify that the request ran as expected.
2196 EXPECT_EQ(OK
, callback2
.WaitForResult());
2197 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2199 // Check that the expected events were output to the log stream. In particular
2200 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2201 // setup), and NOT a second time when the IP address changed.
2202 CapturingNetLog::CapturedEntryList entries
;
2203 log
.GetEntries(&entries
);
2205 EXPECT_TRUE(LogContainsEntryWithType(entries
, 0,
2206 NetLog::TYPE_PROXY_CONFIG_CHANGED
));
2207 ASSERT_EQ(9u, entries
.size());
2208 for (size_t i
= 1; i
< entries
.size(); ++i
)
2209 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED
, entries
[i
].type
);
2212 // This test verifies that the PAC script specified by the settings is
2213 // periodically polled for changes. Specifically, if the initial fetch fails due
2214 // to a network error, we will eventually re-configure the service to use the
2215 // script once it becomes available.
2216 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterFailure
) {
2217 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2219 ImmediatePollPolicy poll_policy
;
2220 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2222 MockProxyConfigService
* config_service
=
2223 new MockProxyConfigService("http://foopy/proxy.pac");
2225 MockAsyncProxyResolverExpectsBytes
* resolver
=
2226 new MockAsyncProxyResolverExpectsBytes
;
2228 ProxyService
service(config_service
, resolver
, NULL
);
2230 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2231 service
.SetProxyScriptFetchers(fetcher
,
2232 new DoNothingDhcpProxyScriptFetcher());
2237 TestCompletionCallback callback1
;
2238 int rv
= service
.ResolveProxy(
2239 GURL("http://request1"), &info1
, callback1
.callback(),
2240 NULL
, BoundNetLog());
2241 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2243 // The first request should have triggered initial download of PAC script.
2244 EXPECT_TRUE(fetcher
->has_pending_request());
2245 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2247 // Nothing has been sent to the resolver yet.
2248 EXPECT_TRUE(resolver
->pending_requests().empty());
2250 // At this point the ProxyService should be waiting for the
2251 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2252 // PAC script download completion.
2254 // We simulate a failed download attempt, the proxy service should now
2255 // fall-back to DIRECT connections.
2256 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
2258 ASSERT_TRUE(resolver
->pending_requests().empty());
2260 // Wait for completion callback, and verify it used DIRECT.
2261 EXPECT_EQ(OK
, callback1
.WaitForResult());
2262 EXPECT_TRUE(info1
.is_direct());
2264 // At this point we have initialized the proxy service using a PAC script,
2265 // however it failed and fell-back to DIRECT.
2267 // A background task to periodically re-check the PAC script for validity will
2268 // have been started. We will now wait for the next download attempt to start.
2270 // Note that we shouldn't have to wait long here, since our test enables a
2271 // special unit-test mode.
2272 fetcher
->WaitUntilFetch();
2274 ASSERT_TRUE(resolver
->pending_requests().empty());
2276 // Make sure that our background checker is trying to download the expected
2277 // PAC script (same one as before). This time we will simulate a successful
2278 // download of the script.
2279 EXPECT_TRUE(fetcher
->has_pending_request());
2280 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2281 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2283 base::MessageLoop::current()->RunUntilIdle();
2285 // Now that the PAC script is downloaded, it should be used to initialize the
2286 // ProxyResolver. Simulate a successful parse.
2287 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2288 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2289 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2291 // At this point the ProxyService should have re-configured itself to use the
2292 // PAC script (thereby recovering from the initial fetch failure). We will
2293 // verify that the next Resolve request uses the resolver rather than
2296 // Start a second request.
2298 TestCompletionCallback callback2
;
2299 rv
= service
.ResolveProxy(
2300 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2302 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2304 // Check that it was sent to the resolver.
2305 ASSERT_EQ(1u, resolver
->pending_requests().size());
2306 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2308 // Complete the pending second request.
2309 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2310 resolver
->pending_requests()[0]->CompleteNow(OK
);
2312 // Wait for completion callback, and verify that the request ran as expected.
2313 EXPECT_EQ(OK
, callback2
.WaitForResult());
2314 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2317 // This test verifies that the PAC script specified by the settings is
2318 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2319 // however at a later time its *contents* change, we will eventually
2320 // re-configure the service to use the new script.
2321 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterContentChange
) {
2322 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2324 ImmediatePollPolicy poll_policy
;
2325 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2327 MockProxyConfigService
* config_service
=
2328 new MockProxyConfigService("http://foopy/proxy.pac");
2330 MockAsyncProxyResolverExpectsBytes
* resolver
=
2331 new MockAsyncProxyResolverExpectsBytes
;
2333 ProxyService
service(config_service
, resolver
, NULL
);
2335 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2336 service
.SetProxyScriptFetchers(fetcher
,
2337 new DoNothingDhcpProxyScriptFetcher());
2342 TestCompletionCallback callback1
;
2343 int rv
= service
.ResolveProxy(
2344 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2346 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2348 // The first request should have triggered initial download of PAC script.
2349 EXPECT_TRUE(fetcher
->has_pending_request());
2350 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2352 // Nothing has been sent to the resolver yet.
2353 EXPECT_TRUE(resolver
->pending_requests().empty());
2355 // At this point the ProxyService should be waiting for the
2356 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2357 // PAC script download completion.
2358 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2360 // Now that the PAC script is downloaded, the request will have been sent to
2361 // the proxy resolver.
2362 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2363 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2364 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2366 ASSERT_EQ(1u, resolver
->pending_requests().size());
2367 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2369 // Complete the pending request.
2370 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2371 resolver
->pending_requests()[0]->CompleteNow(OK
);
2373 // Wait for completion callback, and verify that the request ran as expected.
2374 EXPECT_EQ(OK
, callback1
.WaitForResult());
2375 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2377 // At this point we have initialized the proxy service using a PAC script.
2379 // A background task to periodically re-check the PAC script for validity will
2380 // have been started. We will now wait for the next download attempt to start.
2382 // Note that we shouldn't have to wait long here, since our test enables a
2383 // special unit-test mode.
2384 fetcher
->WaitUntilFetch();
2386 ASSERT_TRUE(resolver
->pending_requests().empty());
2388 // Make sure that our background checker is trying to download the expected
2389 // PAC script (same one as before). This time we will simulate a successful
2390 // download of a DIFFERENT script.
2391 EXPECT_TRUE(fetcher
->has_pending_request());
2392 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2393 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript2
);
2395 base::MessageLoop::current()->RunUntilIdle();
2397 // Now that the PAC script is downloaded, it should be used to initialize the
2398 // ProxyResolver. Simulate a successful parse.
2399 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2
),
2400 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2401 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2403 // At this point the ProxyService should have re-configured itself to use the
2406 // Start a second request.
2408 TestCompletionCallback callback2
;
2409 rv
= service
.ResolveProxy(
2410 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2412 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2414 // Check that it was sent to the resolver.
2415 ASSERT_EQ(1u, resolver
->pending_requests().size());
2416 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2418 // Complete the pending second request.
2419 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2420 resolver
->pending_requests()[0]->CompleteNow(OK
);
2422 // Wait for completion callback, and verify that the request ran as expected.
2423 EXPECT_EQ(OK
, callback2
.WaitForResult());
2424 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2427 // This test verifies that the PAC script specified by the settings is
2428 // periodically polled for changes. Specifically, if the initial fetch succeeds
2429 // and so does the next poll, however the contents of the downloaded script
2430 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2431 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterContentUnchanged
) {
2432 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2434 ImmediatePollPolicy poll_policy
;
2435 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2437 MockProxyConfigService
* config_service
=
2438 new MockProxyConfigService("http://foopy/proxy.pac");
2440 MockAsyncProxyResolverExpectsBytes
* resolver
=
2441 new MockAsyncProxyResolverExpectsBytes
;
2443 ProxyService
service(config_service
, resolver
, NULL
);
2445 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2446 service
.SetProxyScriptFetchers(fetcher
,
2447 new DoNothingDhcpProxyScriptFetcher());
2452 TestCompletionCallback callback1
;
2453 int rv
= service
.ResolveProxy(
2454 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2456 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2458 // The first request should have triggered initial download of PAC script.
2459 EXPECT_TRUE(fetcher
->has_pending_request());
2460 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2462 // Nothing has been sent to the resolver yet.
2463 EXPECT_TRUE(resolver
->pending_requests().empty());
2465 // At this point the ProxyService should be waiting for the
2466 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2467 // PAC script download completion.
2468 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2470 // Now that the PAC script is downloaded, the request will have been sent to
2471 // the proxy resolver.
2472 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2473 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2474 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2476 ASSERT_EQ(1u, resolver
->pending_requests().size());
2477 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2479 // Complete the pending request.
2480 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2481 resolver
->pending_requests()[0]->CompleteNow(OK
);
2483 // Wait for completion callback, and verify that the request ran as expected.
2484 EXPECT_EQ(OK
, callback1
.WaitForResult());
2485 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2487 // At this point we have initialized the proxy service using a PAC script.
2489 // A background task to periodically re-check the PAC script for validity will
2490 // have been started. We will now wait for the next download attempt to start.
2492 // Note that we shouldn't have to wait long here, since our test enables a
2493 // special unit-test mode.
2494 fetcher
->WaitUntilFetch();
2496 ASSERT_TRUE(resolver
->pending_requests().empty());
2498 // Make sure that our background checker is trying to download the expected
2499 // PAC script (same one as before). We will simulate the same response as
2500 // last time (i.e. the script is unchanged).
2501 EXPECT_TRUE(fetcher
->has_pending_request());
2502 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2503 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2505 base::MessageLoop::current()->RunUntilIdle();
2507 ASSERT_FALSE(resolver
->has_pending_set_pac_script_request());
2509 // At this point the ProxyService is still running the same PAC script as
2512 // Start a second request.
2514 TestCompletionCallback callback2
;
2515 rv
= service
.ResolveProxy(
2516 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2518 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2520 // Check that it was sent to the resolver.
2521 ASSERT_EQ(1u, resolver
->pending_requests().size());
2522 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2524 // Complete the pending second request.
2525 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2526 resolver
->pending_requests()[0]->CompleteNow(OK
);
2528 // Wait for completion callback, and verify that the request ran as expected.
2529 EXPECT_EQ(OK
, callback2
.WaitForResult());
2530 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2533 // This test verifies that the PAC script specified by the settings is
2534 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2535 // however at a later time it starts to fail, we should re-configure the
2536 // ProxyService to stop using that PAC script.
2537 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterSuccess
) {
2538 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2540 ImmediatePollPolicy poll_policy
;
2541 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2543 MockProxyConfigService
* config_service
=
2544 new MockProxyConfigService("http://foopy/proxy.pac");
2546 MockAsyncProxyResolverExpectsBytes
* resolver
=
2547 new MockAsyncProxyResolverExpectsBytes
;
2549 ProxyService
service(config_service
, resolver
, NULL
);
2551 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2552 service
.SetProxyScriptFetchers(fetcher
,
2553 new DoNothingDhcpProxyScriptFetcher());
2558 TestCompletionCallback callback1
;
2559 int rv
= service
.ResolveProxy(
2560 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2562 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2564 // The first request should have triggered initial download of PAC script.
2565 EXPECT_TRUE(fetcher
->has_pending_request());
2566 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2568 // Nothing has been sent to the resolver yet.
2569 EXPECT_TRUE(resolver
->pending_requests().empty());
2571 // At this point the ProxyService should be waiting for the
2572 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2573 // PAC script download completion.
2574 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2576 // Now that the PAC script is downloaded, the request will have been sent to
2577 // the proxy resolver.
2578 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2579 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2580 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2582 ASSERT_EQ(1u, resolver
->pending_requests().size());
2583 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2585 // Complete the pending request.
2586 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2587 resolver
->pending_requests()[0]->CompleteNow(OK
);
2589 // Wait for completion callback, and verify that the request ran as expected.
2590 EXPECT_EQ(OK
, callback1
.WaitForResult());
2591 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2593 // At this point we have initialized the proxy service using a PAC script.
2595 // A background task to periodically re-check the PAC script for validity will
2596 // have been started. We will now wait for the next download attempt to start.
2598 // Note that we shouldn't have to wait long here, since our test enables a
2599 // special unit-test mode.
2600 fetcher
->WaitUntilFetch();
2602 ASSERT_TRUE(resolver
->pending_requests().empty());
2604 // Make sure that our background checker is trying to download the expected
2605 // PAC script (same one as before). This time we will simulate a failure
2606 // to download the script.
2607 EXPECT_TRUE(fetcher
->has_pending_request());
2608 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2609 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
2611 base::MessageLoop::current()->RunUntilIdle();
2613 // At this point the ProxyService should have re-configured itself to use
2614 // DIRECT connections rather than the given proxy resolver.
2616 // Start a second request.
2618 TestCompletionCallback callback2
;
2619 rv
= service
.ResolveProxy(
2620 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2623 EXPECT_TRUE(info2
.is_direct());
2626 // Tests that the code which decides at what times to poll the PAC
2627 // script follows the expected policy.
2628 TEST_F(ProxyServiceTest
, PACScriptPollingPolicy
) {
2629 // Retrieve the internal polling policy implementation used by ProxyService.
2630 scoped_ptr
<ProxyService::PacPollPolicy
> policy
=
2631 ProxyService::CreateDefaultPacPollPolicy();
2634 ProxyService::PacPollPolicy::Mode mode
;
2635 const base::TimeDelta initial_delay
= base::TimeDelta::FromMilliseconds(-1);
2636 base::TimeDelta delay
= initial_delay
;
2638 // --------------------------------------------------
2639 // Test the poll sequence in response to a failure.
2640 // --------------------------------------------------
2641 error
= ERR_NAME_NOT_RESOLVED
;
2644 mode
= policy
->GetNextDelay(error
, initial_delay
, &delay
);
2645 EXPECT_EQ(8, delay
.InSeconds());
2646 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER
, mode
);
2649 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2650 EXPECT_EQ(32, delay
.InSeconds());
2651 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2654 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2655 EXPECT_EQ(120, delay
.InSeconds());
2656 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2659 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2660 EXPECT_EQ(14400, delay
.InSeconds());
2661 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2664 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2665 EXPECT_EQ(14400, delay
.InSeconds());
2666 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2668 // --------------------------------------------------
2669 // Test the poll sequence in response to a success.
2670 // --------------------------------------------------
2674 mode
= policy
->GetNextDelay(error
, initial_delay
, &delay
);
2675 EXPECT_EQ(43200, delay
.InSeconds());
2676 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2679 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2680 EXPECT_EQ(43200, delay
.InSeconds());
2681 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2684 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2685 EXPECT_EQ(43200, delay
.InSeconds());
2686 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2689 // This tests the polling of the PAC script. Specifically, it tests that
2690 // polling occurs in response to user activity.
2691 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterActivity
) {
2692 ImmediateAfterActivityPollPolicy poll_policy
;
2693 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2695 MockProxyConfigService
* config_service
=
2696 new MockProxyConfigService("http://foopy/proxy.pac");
2698 MockAsyncProxyResolverExpectsBytes
* resolver
=
2699 new MockAsyncProxyResolverExpectsBytes
;
2701 ProxyService
service(config_service
, resolver
, NULL
);
2703 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2704 service
.SetProxyScriptFetchers(fetcher
,
2705 new DoNothingDhcpProxyScriptFetcher());
2710 TestCompletionCallback callback1
;
2711 int rv
= service
.ResolveProxy(
2712 GURL("http://request1"), &info1
, callback1
.callback(), NULL
,
2714 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2716 // The first request should have triggered initial download of PAC script.
2717 EXPECT_TRUE(fetcher
->has_pending_request());
2718 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2720 // Nothing has been sent to the resolver yet.
2721 EXPECT_TRUE(resolver
->pending_requests().empty());
2723 // At this point the ProxyService should be waiting for the
2724 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2725 // PAC script download completion.
2726 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2728 // Now that the PAC script is downloaded, the request will have been sent to
2729 // the proxy resolver.
2730 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2731 resolver
->pending_set_pac_script_request()->script_data()->utf16());
2732 resolver
->pending_set_pac_script_request()->CompleteNow(OK
);
2734 ASSERT_EQ(1u, resolver
->pending_requests().size());
2735 EXPECT_EQ(GURL("http://request1"), resolver
->pending_requests()[0]->url());
2737 // Complete the pending request.
2738 resolver
->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2739 resolver
->pending_requests()[0]->CompleteNow(OK
);
2741 // Wait for completion callback, and verify that the request ran as expected.
2742 EXPECT_EQ(OK
, callback1
.WaitForResult());
2743 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2745 // At this point we have initialized the proxy service using a PAC script.
2746 // Our PAC poller is set to update ONLY in response to network activity,
2747 // (i.e. another call to ResolveProxy()).
2749 ASSERT_FALSE(fetcher
->has_pending_request());
2750 ASSERT_TRUE(resolver
->pending_requests().empty());
2752 // Start a second request.
2754 TestCompletionCallback callback2
;
2755 rv
= service
.ResolveProxy(
2756 GURL("http://request2"), &info2
, callback2
.callback(), NULL
,
2758 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2760 // This request should have sent work to the resolver; complete it.
2761 ASSERT_EQ(1u, resolver
->pending_requests().size());
2762 EXPECT_EQ(GURL("http://request2"), resolver
->pending_requests()[0]->url());
2763 resolver
->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2764 resolver
->pending_requests()[0]->CompleteNow(OK
);
2766 EXPECT_EQ(OK
, callback2
.WaitForResult());
2767 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2769 // In response to getting that resolve request, the poller should have
2770 // started the next poll, and made it as far as to request the download.
2772 EXPECT_TRUE(fetcher
->has_pending_request());
2773 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2775 // This time we will fail the download, to simulate a PAC script change.
2776 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
2778 // Drain the message loop, so ProxyService is notified of the change
2779 // and has a chance to re-configure itself.
2780 base::MessageLoop::current()->RunUntilIdle();
2782 // Start a third request -- this time we expect to get a direct connection
2783 // since the PAC script poller experienced a failure.
2785 TestCompletionCallback callback3
;
2786 rv
= service
.ResolveProxy(
2787 GURL("http://request3"), &info3
, callback3
.callback(), NULL
,
2790 EXPECT_TRUE(info3
.is_direct());