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.
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/net_log.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/dns/mock_host_resolver.h"
19 #include "net/proxy/dhcp_proxy_script_fetcher.h"
20 #include "net/proxy/mock_proxy_script_fetcher.h"
21 #include "net/proxy/proxy_config.h"
22 #include "net/proxy/proxy_resolver.h"
23 #include "net/proxy/proxy_script_decider.h"
24 #include "net/proxy/proxy_script_fetcher.h"
25 #include "net/url_request/url_request_context.h"
26 #include "testing/gtest/include/gtest/gtest.h"
32 kFailedDownloading
= -100,
33 kFailedParsing
= ERR_PAC_SCRIPT_FAILED
,
39 Rule(const GURL
& url
, int fetch_error
, bool is_valid_script
)
41 fetch_error(fetch_error
),
42 is_valid_script(is_valid_script
) {
45 base::string16
text() const {
47 return base::UTF8ToUTF16(url
.spec() + "!FindProxyForURL");
48 if (fetch_error
== OK
)
49 return base::UTF8ToUTF16(url
.spec() + "!invalid-script");
50 return base::string16();
58 Rule
AddSuccessRule(const char* url
) {
59 Rule
rule(GURL(url
), OK
/*fetch_error*/, true);
60 rules_
.push_back(rule
);
64 void AddFailDownloadRule(const char* url
) {
65 rules_
.push_back(Rule(GURL(url
), kFailedDownloading
/*fetch_error*/,
69 void AddFailParsingRule(const char* url
) {
70 rules_
.push_back(Rule(GURL(url
), OK
/*fetch_error*/, false));
73 const Rule
& GetRuleByUrl(const GURL
& url
) const {
74 for (RuleList::const_iterator it
= rules_
.begin(); it
!= rules_
.end();
79 LOG(FATAL
) << "Rule not found for " << url
;
83 const Rule
& GetRuleByText(const base::string16
& text
) const {
84 for (RuleList::const_iterator it
= rules_
.begin(); it
!= rules_
.end();
86 if (it
->text() == text
)
89 LOG(FATAL
) << "Rule not found for " << text
;
94 typedef std::vector
<Rule
> RuleList
;
98 class RuleBasedProxyScriptFetcher
: public ProxyScriptFetcher
{
100 explicit RuleBasedProxyScriptFetcher(const Rules
* rules
)
101 : rules_(rules
), request_context_(NULL
) {}
103 virtual void SetRequestContext(URLRequestContext
* context
) {
104 request_context_
= context
;
107 // ProxyScriptFetcher implementation.
108 virtual int Fetch(const GURL
& url
,
109 base::string16
* text
,
110 const CompletionCallback
& callback
) OVERRIDE
{
111 const Rules::Rule
& rule
= rules_
->GetRuleByUrl(url
);
112 int rv
= rule
.fetch_error
;
113 EXPECT_NE(ERR_UNEXPECTED
, rv
);
119 virtual void Cancel() OVERRIDE
{}
121 virtual URLRequestContext
* GetRequestContext() const OVERRIDE
{
122 return request_context_
;
127 URLRequestContext
* request_context_
;
130 // A mock retriever, returns asynchronously when CompleteRequests() is called.
131 class MockDhcpProxyScriptFetcher
: public DhcpProxyScriptFetcher
{
133 MockDhcpProxyScriptFetcher();
134 virtual ~MockDhcpProxyScriptFetcher();
136 virtual int Fetch(base::string16
* utf16_text
,
137 const CompletionCallback
& callback
) OVERRIDE
;
138 virtual void Cancel() OVERRIDE
;
139 virtual const GURL
& GetPacURL() const OVERRIDE
;
141 virtual void SetPacURL(const GURL
& url
);
143 virtual void CompleteRequests(int result
, const base::string16
& script
);
146 CompletionCallback callback_
;
147 base::string16
* utf16_text_
;
149 DISALLOW_COPY_AND_ASSIGN(MockDhcpProxyScriptFetcher
);
152 MockDhcpProxyScriptFetcher::MockDhcpProxyScriptFetcher() { }
154 MockDhcpProxyScriptFetcher::~MockDhcpProxyScriptFetcher() { }
156 int MockDhcpProxyScriptFetcher::Fetch(base::string16
* utf16_text
,
157 const CompletionCallback
& callback
) {
158 utf16_text_
= utf16_text
;
159 callback_
= callback
;
160 return ERR_IO_PENDING
;
163 void MockDhcpProxyScriptFetcher::Cancel() { }
165 const GURL
& MockDhcpProxyScriptFetcher::GetPacURL() const {
169 void MockDhcpProxyScriptFetcher::SetPacURL(const GURL
& url
) {
173 void MockDhcpProxyScriptFetcher::CompleteRequests(
174 int result
, const base::string16
& script
) {
175 *utf16_text_
= script
;
176 callback_
.Run(result
);
179 // Succeed using custom PAC script.
180 TEST(ProxyScriptDeciderTest
, CustomPacSucceeds
) {
182 RuleBasedProxyScriptFetcher
fetcher(&rules
);
183 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
186 config
.set_pac_url(GURL("http://custom/proxy.pac"));
188 Rules::Rule rule
= rules
.AddSuccessRule("http://custom/proxy.pac");
190 TestCompletionCallback callback
;
192 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
193 EXPECT_EQ(OK
, decider
.Start(
194 config
, base::TimeDelta(), true, callback
.callback()));
195 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
197 // Check the NetLog was filled correctly.
198 CapturingNetLog::CapturedEntryList entries
;
199 log
.GetEntries(&entries
);
201 EXPECT_EQ(4u, entries
.size());
202 EXPECT_TRUE(LogContainsBeginEvent(
203 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
204 EXPECT_TRUE(LogContainsBeginEvent(
205 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
206 EXPECT_TRUE(LogContainsEndEvent(
207 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
208 EXPECT_TRUE(LogContainsEndEvent(
209 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
211 EXPECT_TRUE(decider
.effective_config().has_pac_url());
212 EXPECT_EQ(config
.pac_url(), decider
.effective_config().pac_url());
215 // Fail downloading the custom PAC script.
216 TEST(ProxyScriptDeciderTest
, CustomPacFails1
) {
218 RuleBasedProxyScriptFetcher
fetcher(&rules
);
219 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
222 config
.set_pac_url(GURL("http://custom/proxy.pac"));
224 rules
.AddFailDownloadRule("http://custom/proxy.pac");
226 TestCompletionCallback callback
;
228 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
229 EXPECT_EQ(kFailedDownloading
,
230 decider
.Start(config
, base::TimeDelta(), true,
231 callback
.callback()));
232 EXPECT_EQ(NULL
, decider
.script_data());
234 // Check the NetLog was filled correctly.
235 CapturingNetLog::CapturedEntryList entries
;
236 log
.GetEntries(&entries
);
238 EXPECT_EQ(4u, entries
.size());
239 EXPECT_TRUE(LogContainsBeginEvent(
240 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
241 EXPECT_TRUE(LogContainsBeginEvent(
242 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
243 EXPECT_TRUE(LogContainsEndEvent(
244 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
245 EXPECT_TRUE(LogContainsEndEvent(
246 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
248 EXPECT_FALSE(decider
.effective_config().has_pac_url());
251 // Fail parsing the custom PAC script.
252 TEST(ProxyScriptDeciderTest
, CustomPacFails2
) {
254 RuleBasedProxyScriptFetcher
fetcher(&rules
);
255 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
258 config
.set_pac_url(GURL("http://custom/proxy.pac"));
260 rules
.AddFailParsingRule("http://custom/proxy.pac");
262 TestCompletionCallback callback
;
263 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
264 EXPECT_EQ(kFailedParsing
,
265 decider
.Start(config
, base::TimeDelta(), true,
266 callback
.callback()));
267 EXPECT_EQ(NULL
, decider
.script_data());
270 // Fail downloading the custom PAC script, because the fetcher was NULL.
271 TEST(ProxyScriptDeciderTest
, HasNullProxyScriptFetcher
) {
273 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
276 config
.set_pac_url(GURL("http://custom/proxy.pac"));
278 TestCompletionCallback callback
;
279 ProxyScriptDecider
decider(NULL
, &dhcp_fetcher
, NULL
);
280 EXPECT_EQ(ERR_UNEXPECTED
,
281 decider
.Start(config
, base::TimeDelta(), true,
282 callback
.callback()));
283 EXPECT_EQ(NULL
, decider
.script_data());
286 // Succeeds in choosing autodetect (WPAD DNS).
287 TEST(ProxyScriptDeciderTest
, AutodetectSuccess
) {
289 RuleBasedProxyScriptFetcher
fetcher(&rules
);
290 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
293 config
.set_auto_detect(true);
295 Rules::Rule rule
= rules
.AddSuccessRule("http://wpad/wpad.dat");
297 TestCompletionCallback callback
;
298 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
299 EXPECT_EQ(OK
, decider
.Start(
300 config
, base::TimeDelta(), true, callback
.callback()));
301 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
303 EXPECT_TRUE(decider
.effective_config().has_pac_url());
304 EXPECT_EQ(rule
.url
, decider
.effective_config().pac_url());
307 class ProxyScriptDeciderQuickCheckTest
: public ::testing::Test
{
309 ProxyScriptDeciderQuickCheckTest()
310 : rule_(rules_
.AddSuccessRule("http://wpad/wpad.dat")),
311 fetcher_(&rules_
) { }
313 virtual void SetUp() OVERRIDE
{
314 request_context_
.set_host_resolver(&resolver_
);
315 fetcher_
.SetRequestContext(&request_context_
);
316 config_
.set_auto_detect(true);
317 decider_
.reset(new ProxyScriptDecider(&fetcher_
, &dhcp_fetcher_
, NULL
));
321 return decider_
->Start(config_
, base::TimeDelta(), true,
322 callback_
.callback());
326 scoped_ptr
<ProxyScriptDecider
> decider_
;
327 MockHostResolver resolver_
;
330 TestCompletionCallback callback_
;
331 RuleBasedProxyScriptFetcher fetcher_
;
333 DoNothingDhcpProxyScriptFetcher dhcp_fetcher_
;
336 URLRequestContext request_context_
;
339 // Fails if a synchronous DNS lookup success for wpad causes QuickCheck to fail.
340 TEST_F(ProxyScriptDeciderQuickCheckTest
, SyncSuccess
) {
341 resolver_
.set_synchronous_mode(true);
342 resolver_
.rules()->AddRule("wpad", "1.2.3.4");
344 EXPECT_EQ(OK
, StartDecider());
345 EXPECT_EQ(rule_
.text(), decider_
->script_data()->utf16());
347 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
348 EXPECT_EQ(rule_
.url
, decider_
->effective_config().pac_url());
351 // Fails if an asynchronous DNS lookup success for wpad causes QuickCheck to
353 TEST_F(ProxyScriptDeciderQuickCheckTest
, AsyncSuccess
) {
354 resolver_
.set_ondemand_mode(true);
355 resolver_
.rules()->AddRule("wpad", "1.2.3.4");
357 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
358 ASSERT_TRUE(resolver_
.has_pending_requests());
359 resolver_
.ResolveAllPending();
360 callback_
.WaitForResult();
361 EXPECT_FALSE(resolver_
.has_pending_requests());
362 EXPECT_EQ(rule_
.text(), decider_
->script_data()->utf16());
363 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
364 EXPECT_EQ(rule_
.url
, decider_
->effective_config().pac_url());
367 // Fails if an asynchronous DNS lookup failure (i.e. an NXDOMAIN) still causes
368 // ProxyScriptDecider to yield a PAC URL.
369 TEST_F(ProxyScriptDeciderQuickCheckTest
, AsyncFail
) {
370 resolver_
.set_ondemand_mode(true);
371 resolver_
.rules()->AddSimulatedFailure("wpad");
372 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
373 ASSERT_TRUE(resolver_
.has_pending_requests());
374 resolver_
.ResolveAllPending();
375 callback_
.WaitForResult();
376 EXPECT_FALSE(decider_
->effective_config().has_pac_url());
379 // Fails if a DNS lookup timeout either causes ProxyScriptDecider to yield a PAC
380 // URL or causes ProxyScriptDecider not to cancel its pending resolution.
381 TEST_F(ProxyScriptDeciderQuickCheckTest
, AsyncTimeout
) {
382 resolver_
.set_ondemand_mode(true);
383 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
384 ASSERT_TRUE(resolver_
.has_pending_requests());
385 callback_
.WaitForResult();
386 EXPECT_FALSE(resolver_
.has_pending_requests());
387 EXPECT_FALSE(decider_
->effective_config().has_pac_url());
390 // Fails if DHCP check doesn't take place before QuickCheck.
391 TEST_F(ProxyScriptDeciderQuickCheckTest
, QuickCheckInhibitsDhcp
) {
392 MockDhcpProxyScriptFetcher dhcp_fetcher
;
393 const char *kPac
= "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
394 base::string16 pac_contents
= base::UTF8ToUTF16(kPac
);
395 GURL
url("http://foobar/baz");
396 dhcp_fetcher
.SetPacURL(url
);
397 decider_
.reset(new ProxyScriptDecider(&fetcher_
, &dhcp_fetcher
, NULL
));
398 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
399 dhcp_fetcher
.CompleteRequests(OK
, pac_contents
);
400 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
401 EXPECT_EQ(decider_
->effective_config().pac_url(), url
);
404 // Fails if QuickCheck still happens when disabled. To ensure QuickCheck is not
405 // happening, we add a synchronous failing resolver, which would ordinarily
406 // mean a QuickCheck failure, then ensure that our ProxyScriptFetcher is still
408 TEST_F(ProxyScriptDeciderQuickCheckTest
, QuickCheckDisabled
) {
409 const char *kPac
= "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
410 resolver_
.set_synchronous_mode(true);
411 resolver_
.rules()->AddSimulatedFailure("wpad");
412 MockProxyScriptFetcher fetcher
;
413 decider_
.reset(new ProxyScriptDecider(&fetcher
, &dhcp_fetcher_
, NULL
));
414 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
415 EXPECT_TRUE(fetcher
.has_pending_request());
416 fetcher
.NotifyFetchCompletion(OK
, kPac
);
419 TEST_F(ProxyScriptDeciderQuickCheckTest
, ExplicitPacUrl
) {
420 const char *kCustomUrl
= "http://custom/proxy.pac";
421 config_
.set_pac_url(GURL(kCustomUrl
));
422 Rules::Rule rule
= rules_
.AddSuccessRule(kCustomUrl
);
423 resolver_
.rules()->AddSimulatedFailure("wpad");
424 resolver_
.rules()->AddRule("custom", "1.2.3.4");
425 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
426 callback_
.WaitForResult();
427 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
428 EXPECT_EQ(rule
.url
, decider_
->effective_config().pac_url());
431 // Fails at WPAD (downloading), but succeeds in choosing the custom PAC.
432 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomSuccess1
) {
434 RuleBasedProxyScriptFetcher
fetcher(&rules
);
435 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
438 config
.set_auto_detect(true);
439 config
.set_pac_url(GURL("http://custom/proxy.pac"));
441 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
442 Rules::Rule rule
= rules
.AddSuccessRule("http://custom/proxy.pac");
444 TestCompletionCallback callback
;
445 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
446 EXPECT_EQ(OK
, decider
.Start(
447 config
, base::TimeDelta(), true, callback
.callback()));
448 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
450 EXPECT_TRUE(decider
.effective_config().has_pac_url());
451 EXPECT_EQ(rule
.url
, decider
.effective_config().pac_url());
454 // Fails at WPAD (no DHCP config, DNS PAC fails parsing), but succeeds in
455 // choosing the custom PAC.
456 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomSuccess2
) {
458 RuleBasedProxyScriptFetcher
fetcher(&rules
);
459 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
462 config
.set_auto_detect(true);
463 config
.set_pac_url(GURL("http://custom/proxy.pac"));
464 config
.proxy_rules().ParseFromString("unused-manual-proxy:99");
466 rules
.AddFailParsingRule("http://wpad/wpad.dat");
467 Rules::Rule rule
= rules
.AddSuccessRule("http://custom/proxy.pac");
469 TestCompletionCallback callback
;
472 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
473 EXPECT_EQ(OK
, decider
.Start(config
, base::TimeDelta(),
474 true, callback
.callback()));
475 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
477 // Verify that the effective configuration no longer contains auto detect or
478 // any of the manual settings.
479 EXPECT_TRUE(decider
.effective_config().Equals(
480 ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac"))));
482 // Check the NetLog was filled correctly.
483 // (Note that various states are repeated since both WPAD and custom
484 // PAC scripts are tried).
485 CapturingNetLog::CapturedEntryList entries
;
486 log
.GetEntries(&entries
);
488 EXPECT_EQ(10u, entries
.size());
489 EXPECT_TRUE(LogContainsBeginEvent(
490 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
491 // This is the DHCP phase, which fails fetching rather than parsing, so
492 // there is no pair of SET_PAC_SCRIPT events.
493 EXPECT_TRUE(LogContainsBeginEvent(
494 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
495 EXPECT_TRUE(LogContainsEndEvent(
496 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
497 EXPECT_TRUE(LogContainsEvent(
499 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE
,
500 NetLog::PHASE_NONE
));
501 // This is the DNS phase, which attempts a fetch but fails.
502 EXPECT_TRUE(LogContainsBeginEvent(
503 entries
, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
504 EXPECT_TRUE(LogContainsEndEvent(
505 entries
, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
506 EXPECT_TRUE(LogContainsEvent(
508 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE
,
509 NetLog::PHASE_NONE
));
510 // Finally, the custom PAC URL phase.
511 EXPECT_TRUE(LogContainsBeginEvent(
512 entries
, 7, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
513 EXPECT_TRUE(LogContainsEndEvent(
514 entries
, 8, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
515 EXPECT_TRUE(LogContainsEndEvent(
516 entries
, 9, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
519 // Fails at WPAD (downloading), and fails at custom PAC (downloading).
520 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomFails1
) {
522 RuleBasedProxyScriptFetcher
fetcher(&rules
);
523 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
526 config
.set_auto_detect(true);
527 config
.set_pac_url(GURL("http://custom/proxy.pac"));
529 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
530 rules
.AddFailDownloadRule("http://custom/proxy.pac");
532 TestCompletionCallback callback
;
533 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
534 EXPECT_EQ(kFailedDownloading
,
535 decider
.Start(config
, base::TimeDelta(), true,
536 callback
.callback()));
537 EXPECT_EQ(NULL
, decider
.script_data());
540 // Fails at WPAD (downloading), and fails at custom PAC (parsing).
541 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomFails2
) {
543 RuleBasedProxyScriptFetcher
fetcher(&rules
);
544 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
547 config
.set_auto_detect(true);
548 config
.set_pac_url(GURL("http://custom/proxy.pac"));
550 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
551 rules
.AddFailParsingRule("http://custom/proxy.pac");
553 TestCompletionCallback callback
;
554 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
555 EXPECT_EQ(kFailedParsing
,
556 decider
.Start(config
, base::TimeDelta(), true,
557 callback
.callback()));
558 EXPECT_EQ(NULL
, decider
.script_data());
561 // This is a copy-paste of CustomPacFails1, with the exception that we give it
562 // a 1 millisecond delay. This means it will now complete asynchronously.
563 // Moreover, we test the NetLog to make sure it logged the pause.
564 TEST(ProxyScriptDeciderTest
, CustomPacFails1_WithPositiveDelay
) {
566 RuleBasedProxyScriptFetcher
fetcher(&rules
);
567 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
570 config
.set_pac_url(GURL("http://custom/proxy.pac"));
572 rules
.AddFailDownloadRule("http://custom/proxy.pac");
574 TestCompletionCallback callback
;
576 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
577 EXPECT_EQ(ERR_IO_PENDING
,
578 decider
.Start(config
, base::TimeDelta::FromMilliseconds(1),
579 true, callback
.callback()));
581 EXPECT_EQ(kFailedDownloading
, callback
.WaitForResult());
582 EXPECT_EQ(NULL
, decider
.script_data());
584 // Check the NetLog was filled correctly.
585 CapturingNetLog::CapturedEntryList entries
;
586 log
.GetEntries(&entries
);
588 EXPECT_EQ(6u, entries
.size());
589 EXPECT_TRUE(LogContainsBeginEvent(
590 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
591 EXPECT_TRUE(LogContainsBeginEvent(
592 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT
));
593 EXPECT_TRUE(LogContainsEndEvent(
594 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT
));
595 EXPECT_TRUE(LogContainsBeginEvent(
596 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
597 EXPECT_TRUE(LogContainsEndEvent(
598 entries
, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
599 EXPECT_TRUE(LogContainsEndEvent(
600 entries
, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
603 // This is a copy-paste of CustomPacFails1, with the exception that we give it
604 // a -5 second delay instead of a 0 ms delay. This change should have no effect
605 // so the rest of the test is unchanged.
606 TEST(ProxyScriptDeciderTest
, CustomPacFails1_WithNegativeDelay
) {
608 RuleBasedProxyScriptFetcher
fetcher(&rules
);
609 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
612 config
.set_pac_url(GURL("http://custom/proxy.pac"));
614 rules
.AddFailDownloadRule("http://custom/proxy.pac");
616 TestCompletionCallback callback
;
618 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
619 EXPECT_EQ(kFailedDownloading
,
620 decider
.Start(config
, base::TimeDelta::FromSeconds(-5),
621 true, callback
.callback()));
622 EXPECT_EQ(NULL
, decider
.script_data());
624 // Check the NetLog was filled correctly.
625 CapturingNetLog::CapturedEntryList entries
;
626 log
.GetEntries(&entries
);
628 EXPECT_EQ(4u, entries
.size());
629 EXPECT_TRUE(LogContainsBeginEvent(
630 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
631 EXPECT_TRUE(LogContainsBeginEvent(
632 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
633 EXPECT_TRUE(LogContainsEndEvent(
634 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
635 EXPECT_TRUE(LogContainsEndEvent(
636 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
639 class SynchronousSuccessDhcpFetcher
: public DhcpProxyScriptFetcher
{
641 explicit SynchronousSuccessDhcpFetcher(const base::string16
& expected_text
)
642 : gurl_("http://dhcppac/"), expected_text_(expected_text
) {
645 virtual int Fetch(base::string16
* utf16_text
,
646 const CompletionCallback
& callback
) OVERRIDE
{
647 *utf16_text
= expected_text_
;
651 virtual void Cancel() OVERRIDE
{
654 virtual const GURL
& GetPacURL() const OVERRIDE
{
658 const base::string16
& expected_text() const {
659 return expected_text_
;
664 base::string16 expected_text_
;
666 DISALLOW_COPY_AND_ASSIGN(SynchronousSuccessDhcpFetcher
);
669 // All of the tests above that use ProxyScriptDecider have tested
670 // failure to fetch a PAC file via DHCP configuration, so we now test
671 // success at downloading and parsing, and then success at downloading,
672 // failure at parsing.
674 TEST(ProxyScriptDeciderTest
, AutodetectDhcpSuccess
) {
676 RuleBasedProxyScriptFetcher
fetcher(&rules
);
677 SynchronousSuccessDhcpFetcher
dhcp_fetcher(
678 base::WideToUTF16(L
"http://bingo/!FindProxyForURL"));
681 config
.set_auto_detect(true);
683 rules
.AddSuccessRule("http://bingo/");
684 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
686 TestCompletionCallback callback
;
687 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
688 EXPECT_EQ(OK
, decider
.Start(
689 config
, base::TimeDelta(), true, callback
.callback()));
690 EXPECT_EQ(dhcp_fetcher
.expected_text(),
691 decider
.script_data()->utf16());
693 EXPECT_TRUE(decider
.effective_config().has_pac_url());
694 EXPECT_EQ(GURL("http://dhcppac/"), decider
.effective_config().pac_url());
697 TEST(ProxyScriptDeciderTest
, AutodetectDhcpFailParse
) {
699 RuleBasedProxyScriptFetcher
fetcher(&rules
);
700 SynchronousSuccessDhcpFetcher
dhcp_fetcher(
701 base::WideToUTF16(L
"http://bingo/!invalid-script"));
704 config
.set_auto_detect(true);
706 rules
.AddFailParsingRule("http://bingo/");
707 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
709 TestCompletionCallback callback
;
710 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
711 // Since there is fallback to DNS-based WPAD, the final error will be that
712 // it failed downloading, not that it failed parsing.
713 EXPECT_EQ(kFailedDownloading
,
714 decider
.Start(config
, base::TimeDelta(), true, callback
.callback()));
715 EXPECT_EQ(NULL
, decider
.script_data());
717 EXPECT_FALSE(decider
.effective_config().has_pac_url());
720 class AsyncFailDhcpFetcher
721 : public DhcpProxyScriptFetcher
,
722 public base::SupportsWeakPtr
<AsyncFailDhcpFetcher
> {
724 AsyncFailDhcpFetcher() {}
725 virtual ~AsyncFailDhcpFetcher() {}
727 virtual int Fetch(base::string16
* utf16_text
,
728 const CompletionCallback
& callback
) OVERRIDE
{
729 callback_
= callback
;
730 base::MessageLoop::current()->PostTask(
732 base::Bind(&AsyncFailDhcpFetcher::CallbackWithFailure
, AsWeakPtr()));
733 return ERR_IO_PENDING
;
736 virtual void Cancel() OVERRIDE
{
740 virtual const GURL
& GetPacURL() const OVERRIDE
{
744 void CallbackWithFailure() {
745 if (!callback_
.is_null())
746 callback_
.Run(ERR_PAC_NOT_IN_DHCP
);
751 CompletionCallback callback_
;
754 TEST(ProxyScriptDeciderTest
, DhcpCancelledByDestructor
) {
755 // This regression test would crash before
756 // http://codereview.chromium.org/7044058/
757 // Thus, we don't care much about actual results (hence no EXPECT or ASSERT
758 // macros below), just that it doesn't crash.
760 RuleBasedProxyScriptFetcher
fetcher(&rules
);
762 scoped_ptr
<AsyncFailDhcpFetcher
> dhcp_fetcher(new AsyncFailDhcpFetcher());
765 config
.set_auto_detect(true);
766 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
768 TestCompletionCallback callback
;
770 // Scope so ProxyScriptDecider gets destroyed early.
772 ProxyScriptDecider
decider(&fetcher
, dhcp_fetcher
.get(), NULL
);
773 decider
.Start(config
, base::TimeDelta(), true, callback
.callback());
776 // Run the message loop to let the DHCP fetch complete and post the results
777 // back. Before the fix linked to above, this would try to invoke on
778 // the callback object provided by ProxyScriptDecider after it was
780 base::MessageLoop::current()->RunUntilIdle();