Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / net / proxy / proxy_service_unittest.cc
blobbad5afd62c78f2ca32090d57dc99bbbd8f36cd14
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/proxy/proxy_service.h"
7 #include <vector>
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "net/base/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"
24 #include "url/gurl.h"
26 using base::ASCIIToUTF16;
28 // TODO(eroman): Write a test which exercises
29 // ProxyService::SuspendAllPendingRequests().
30 namespace net {
31 namespace {
33 // This polling policy will decide to poll every 1 ms.
34 class ImmediatePollPolicy : public ProxyService::PacPollPolicy {
35 public:
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;
44 private:
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 {
51 public:
52 NeverPollPolicy() {}
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;
60 private:
61 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy);
64 // This polling policy starts a poll immediately after network activity.
65 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
66 public:
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;
75 private:
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
85 // these tests.
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 {
95 protected:
96 virtual void SetUp() OVERRIDE {
97 testing::Test::SetUp();
98 previous_policy_ =
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();
108 private:
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 {
117 public:
118 explicit MockProxyConfigService(const ProxyConfig& config)
119 : availability_(CONFIG_VALID),
120 config_(config) {
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)
137 OVERRIDE {
138 if (availability_ == CONFIG_VALID)
139 *results = config_;
140 return availability_;
143 void SetConfig(const ProxyConfig& config) {
144 availability_ = CONFIG_VALID;
145 config_ = config;
146 FOR_EACH_OBSERVER(Observer, observers_,
147 OnProxyConfigChanged(config_, availability_));
150 private:
151 ConfigAvailability availability_;
152 ProxyConfig config_;
153 ObserverList<Observer, true> observers_;
156 } // namespace
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/");
165 ProxyInfo info;
166 TestCompletionCallback callback;
167 CapturingBoundNetLog log;
168 int rv = service.ResolveProxy(
169 url, &info, callback.callback(), NULL, log.bound());
170 EXPECT_EQ(OK, rv);
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/");
201 ProxyInfo info;
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");
259 ProxyInfo info;
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/");
287 ProxyInfo info;
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
315 // DIRECT.
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/");
335 ProxyInfo info;
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
354 // DIRECT.
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/");
390 ProxyInfo info;
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());
411 // Fallback 1.
412 TestCompletionCallback callback2;
413 rv = service.ReconsiderProxyAfterError(url, &info, callback2.callback(), NULL,
414 BoundNetLog());
415 EXPECT_EQ(OK, rv);
416 EXPECT_FALSE(info.is_direct());
417 EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
419 // Fallback 2.
420 TestCompletionCallback callback3;
421 rv = service.ReconsiderProxyAfterError(url, &info, callback3.callback(), NULL,
422 BoundNetLog());
423 EXPECT_EQ(OK, rv);
424 EXPECT_TRUE(info.is_direct());
426 // Fallback 3.
427 TestCompletionCallback callback4;
428 rv = service.ReconsiderProxyAfterError(url, &info, callback4.callback(), NULL,
429 BoundNetLog());
430 EXPECT_EQ(OK, rv);
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,
437 BoundNetLog());
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.
445 ProxyConfig config =
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/");
455 ProxyInfo info;
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/");
490 ProxyInfo info;
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.
540 ProxyConfig config(
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/");
552 ProxyInfo info;
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.
584 ProxyConfig config(
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/");
601 ProxyInfo info;
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().
632 ProxyConfig config(
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/");
644 ProxyInfo info;
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
688 // are bad.
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.
700 ProxyInfo info;
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,
732 BoundNetLog());
733 EXPECT_EQ(OK, rv);
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,
774 BoundNetLog());
775 EXPECT_EQ(OK, rv);
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,
783 BoundNetLog());
784 EXPECT_EQ(OK, rv);
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,
791 BoundNetLog());
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,
803 BoundNetLog());
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.
839 ProxyInfo info;
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,
865 BoundNetLog());
866 EXPECT_EQ(OK, rv);
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,
874 BoundNetLog());
875 EXPECT_EQ(OK, rv);
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,
887 BoundNetLog());
888 // There was nothing left to try after DIRECT, so we are out of
889 // choices.
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.
906 ProxyInfo info;
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,
935 BoundNetLog());
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,
956 BoundNetLog());
957 EXPECT_EQ(OK, rv);
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,
968 BoundNetLog());
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.
1003 ProxyInfo info;
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,
1027 BoundNetLog());
1028 EXPECT_EQ(OK, rv);
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.
1035 ProxyInfo info2;
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.
1056 ProxyInfo info3;
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.
1083 ProxyConfig config(
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.
1096 ProxyInfo info;
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,
1120 BoundNetLog());
1121 EXPECT_EQ(OK, rv);
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.
1128 ProxyInfo info2;
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.
1150 ProxyInfo info3;
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];
1174 ProxyInfo info[2];
1175 ProxyConfig config;
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);
1183 int rv;
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());
1190 EXPECT_EQ(OK, rv);
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());
1196 EXPECT_EQ(OK, rv);
1197 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
1201 TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
1202 ProxyConfig config;
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");
1209 ProxyInfo info;
1210 TestCompletionCallback callback;
1211 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1212 BoundNetLog());
1213 EXPECT_EQ(OK, rv);
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");
1221 ProxyInfo info;
1222 TestCompletionCallback callback;
1223 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1224 BoundNetLog());
1225 EXPECT_EQ(OK, rv);
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");
1233 ProxyInfo info;
1234 TestCompletionCallback callback;
1235 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1236 BoundNetLog());
1237 EXPECT_EQ(OK, rv);
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");
1246 ProxyInfo info;
1247 TestCompletionCallback callback;
1248 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1249 BoundNetLog());
1250 EXPECT_EQ(OK, rv);
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.
1261 ProxyConfig config;
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");
1267 ProxyInfo info;
1268 TestCompletionCallback callback;
1269 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1270 BoundNetLog());
1271 ASSERT_EQ(OK, rv);
1272 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1273 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1276 ProxyConfig config;
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");
1282 ProxyInfo info;
1283 TestCompletionCallback callback;
1284 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1285 BoundNetLog());
1286 ASSERT_EQ(OK, rv);
1287 // Used the HTTPS proxy. So source should be TEST.
1288 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1291 ProxyConfig config;
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");
1296 ProxyInfo info;
1297 TestCompletionCallback callback;
1298 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1299 BoundNetLog());
1300 ASSERT_EQ(OK, rv);
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) {
1309 ProxyConfig config;
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");
1319 ProxyInfo info;
1320 TestCompletionCallback callback;
1321 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1322 BoundNetLog());
1323 EXPECT_EQ(OK, rv);
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");
1331 ProxyInfo info;
1332 TestCompletionCallback callback;
1333 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1334 BoundNetLog());
1335 EXPECT_EQ(OK, rv);
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");
1343 ProxyInfo info;
1344 TestCompletionCallback callback;
1345 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1346 BoundNetLog());
1347 EXPECT_EQ(OK, rv);
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");
1355 ProxyInfo info;
1356 TestCompletionCallback callback;
1357 int rv = service.ResolveProxy(test_url, &info, callback.callback(), NULL,
1358 BoundNetLog());
1359 EXPECT_EQ(OK, rv);
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.
1376 ProxyInfo info1;
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());
1394 ProxyInfo info2;
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());
1403 ProxyInfo info3;
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.
1454 ProxyInfo info1;
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());
1465 ProxyInfo info2;
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);
1472 ProxyInfo info3;
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
1495 // resolver.
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.
1557 ProxyInfo info1;
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());
1567 ProxyInfo info2;
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
1590 // resolver.
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.
1615 ProxyInfo info1;
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());
1627 ProxyInfo info2;
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);
1634 ProxyInfo info3;
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
1653 // proxy resolver.
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) {
1692 ProxyConfig config;
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.
1708 ProxyInfo info1;
1709 TestCompletionCallback callback1;
1710 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1711 callback1.callback(), NULL, BoundNetLog());
1712 EXPECT_EQ(ERR_IO_PENDING, rv);
1714 ProxyInfo info2;
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) {
1769 ProxyConfig config;
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.
1785 ProxyInfo info1;
1786 TestCompletionCallback callback1;
1787 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1788 callback1.callback(), NULL, BoundNetLog());
1789 EXPECT_EQ(ERR_IO_PENDING, rv);
1791 ProxyInfo info2;
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) {
1842 ProxyConfig config;
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.
1858 ProxyInfo info1;
1859 TestCompletionCallback callback1;
1860 int rv = service.ResolveProxy(GURL("http://request1"), &info1,
1861 callback1.callback(), NULL, BoundNetLog());
1862 EXPECT_EQ(ERR_IO_PENDING, rv);
1864 ProxyInfo info2;
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
1885 // been sent to it.
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) {
1899 ProxyConfig config;
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.
1916 ProxyInfo info1;
1917 TestCompletionCallback callback1;
1918 int rv = service.ResolveProxy(
1919 GURL("http://www.google.com"), &info1, callback1.callback(), NULL,
1920 BoundNetLog());
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.
1948 ProxyInfo info2;
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());
1983 // Start 1 request.
1985 ProxyInfo info1;
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/");
2014 ProxyInfo info;
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);
2032 ProxyInfo info;
2033 TestCompletionCallback callback1;
2034 int rv = service.ResolveProxy(GURL("http://request1"), &info,
2035 callback1.callback(), NULL, BoundNetLog());
2036 EXPECT_EQ(OK, rv);
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());
2046 EXPECT_EQ(OK, rv);
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);
2059 // Start 1 request.
2061 ProxyInfo info1;
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.
2092 ProxyInfo info2;
2093 TestCompletionCallback callback2;
2094 rv = service.ResolveProxy(GURL("http://www.google.com"), &info2,
2095 callback2.callback(), NULL, BoundNetLog());
2096 EXPECT_EQ(OK, rv);
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());
2120 // Start 1 request.
2122 ProxyInfo info1;
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.
2164 ProxyInfo info2;
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
2179 // different data).
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
2218 // runs quickly.
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());
2234 // Start 1 request.
2236 ProxyInfo info1;
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
2294 // DIRECT.
2296 // Start a second request.
2297 ProxyInfo info2;
2298 TestCompletionCallback callback2;
2299 rv = service.ResolveProxy(
2300 GURL("http://request2"), &info2, callback2.callback(), NULL,
2301 BoundNetLog());
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
2323 // runs quickly.
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());
2339 // Start 1 request.
2341 ProxyInfo info1;
2342 TestCompletionCallback callback1;
2343 int rv = service.ResolveProxy(
2344 GURL("http://request1"), &info1, callback1.callback(), NULL,
2345 BoundNetLog());
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
2404 // new PAC script.
2406 // Start a second request.
2407 ProxyInfo info2;
2408 TestCompletionCallback callback2;
2409 rv = service.ResolveProxy(
2410 GURL("http://request2"), &info2, callback2.callback(), NULL,
2411 BoundNetLog());
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
2433 // runs quickly.
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());
2449 // Start 1 request.
2451 ProxyInfo info1;
2452 TestCompletionCallback callback1;
2453 int rv = service.ResolveProxy(
2454 GURL("http://request1"), &info1, callback1.callback(), NULL,
2455 BoundNetLog());
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
2510 // before.
2512 // Start a second request.
2513 ProxyInfo info2;
2514 TestCompletionCallback callback2;
2515 rv = service.ResolveProxy(
2516 GURL("http://request2"), &info2, callback2.callback(), NULL,
2517 BoundNetLog());
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
2539 // runs quickly.
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());
2555 // Start 1 request.
2557 ProxyInfo info1;
2558 TestCompletionCallback callback1;
2559 int rv = service.ResolveProxy(
2560 GURL("http://request1"), &info1, callback1.callback(), NULL,
2561 BoundNetLog());
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.
2617 ProxyInfo info2;
2618 TestCompletionCallback callback2;
2619 rv = service.ResolveProxy(
2620 GURL("http://request2"), &info2, callback2.callback(), NULL,
2621 BoundNetLog());
2622 EXPECT_EQ(OK, rv);
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();
2633 int error;
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;
2643 // Poll #0
2644 mode = policy->GetNextDelay(error, initial_delay, &delay);
2645 EXPECT_EQ(8, delay.InSeconds());
2646 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
2648 // Poll #1
2649 mode = policy->GetNextDelay(error, delay, &delay);
2650 EXPECT_EQ(32, delay.InSeconds());
2651 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2653 // Poll #2
2654 mode = policy->GetNextDelay(error, delay, &delay);
2655 EXPECT_EQ(120, delay.InSeconds());
2656 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2658 // Poll #3
2659 mode = policy->GetNextDelay(error, delay, &delay);
2660 EXPECT_EQ(14400, delay.InSeconds());
2661 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2663 // Poll #4
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 // --------------------------------------------------
2671 error = OK;
2673 // Poll #0
2674 mode = policy->GetNextDelay(error, initial_delay, &delay);
2675 EXPECT_EQ(43200, delay.InSeconds());
2676 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2678 // Poll #1
2679 mode = policy->GetNextDelay(error, delay, &delay);
2680 EXPECT_EQ(43200, delay.InSeconds());
2681 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2683 // Poll #2
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());
2707 // Start 1 request.
2709 ProxyInfo info1;
2710 TestCompletionCallback callback1;
2711 int rv = service.ResolveProxy(
2712 GURL("http://request1"), &info1, callback1.callback(), NULL,
2713 BoundNetLog());
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.
2753 ProxyInfo info2;
2754 TestCompletionCallback callback2;
2755 rv = service.ResolveProxy(
2756 GURL("http://request2"), &info2, callback2.callback(), NULL,
2757 BoundNetLog());
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.
2784 ProxyInfo info3;
2785 TestCompletionCallback callback3;
2786 rv = service.ResolveProxy(
2787 GURL("http://request3"), &info3, callback3.callback(), NULL,
2788 BoundNetLog());
2789 EXPECT_EQ(OK, rv);
2790 EXPECT_TRUE(info3.is_direct());
2793 } // namespace net