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/test_completion_callback.h"
16 #include "net/dns/mock_host_resolver.h"
17 #include "net/log/net_log.h"
18 #include "net/log/test_net_log.h"
19 #include "net/log/test_net_log_entry.h"
20 #include "net/log/test_net_log_util.h"
21 #include "net/proxy/dhcp_proxy_script_fetcher.h"
22 #include "net/proxy/mock_proxy_script_fetcher.h"
23 #include "net/proxy/proxy_config.h"
24 #include "net/proxy/proxy_resolver.h"
25 #include "net/proxy/proxy_script_decider.h"
26 #include "net/proxy/proxy_script_fetcher.h"
27 #include "net/url_request/url_request_context.h"
28 #include "testing/gtest/include/gtest/gtest.h"
34 kFailedDownloading
= -100,
35 kFailedParsing
= ERR_PAC_SCRIPT_FAILED
,
41 Rule(const GURL
& url
, int fetch_error
, bool is_valid_script
)
43 fetch_error(fetch_error
),
44 is_valid_script(is_valid_script
) {
47 base::string16
text() const {
49 return base::UTF8ToUTF16(url
.spec() + "!FindProxyForURL");
50 if (fetch_error
== OK
)
51 return base::UTF8ToUTF16(url
.spec() + "!invalid-script");
52 return base::string16();
60 Rule
AddSuccessRule(const char* url
) {
61 Rule
rule(GURL(url
), OK
/*fetch_error*/, true);
62 rules_
.push_back(rule
);
66 void AddFailDownloadRule(const char* url
) {
67 rules_
.push_back(Rule(GURL(url
), kFailedDownloading
/*fetch_error*/,
71 void AddFailParsingRule(const char* url
) {
72 rules_
.push_back(Rule(GURL(url
), OK
/*fetch_error*/, false));
75 const Rule
& GetRuleByUrl(const GURL
& url
) const {
76 for (RuleList::const_iterator it
= rules_
.begin(); it
!= rules_
.end();
81 LOG(FATAL
) << "Rule not found for " << url
;
85 const Rule
& GetRuleByText(const base::string16
& text
) const {
86 for (RuleList::const_iterator it
= rules_
.begin(); it
!= rules_
.end();
88 if (it
->text() == text
)
91 LOG(FATAL
) << "Rule not found for " << text
;
96 typedef std::vector
<Rule
> RuleList
;
100 class RuleBasedProxyScriptFetcher
: public ProxyScriptFetcher
{
102 explicit RuleBasedProxyScriptFetcher(const Rules
* rules
)
103 : rules_(rules
), request_context_(NULL
) {}
105 virtual void SetRequestContext(URLRequestContext
* context
) {
106 request_context_
= context
;
109 // ProxyScriptFetcher implementation.
110 int Fetch(const GURL
& url
,
111 base::string16
* text
,
112 const CompletionCallback
& callback
) override
{
113 const Rules::Rule
& rule
= rules_
->GetRuleByUrl(url
);
114 int rv
= rule
.fetch_error
;
115 EXPECT_NE(ERR_UNEXPECTED
, rv
);
121 void Cancel() override
{}
123 URLRequestContext
* GetRequestContext() const override
{
124 return request_context_
;
129 URLRequestContext
* request_context_
;
132 // A mock retriever, returns asynchronously when CompleteRequests() is called.
133 class MockDhcpProxyScriptFetcher
: public DhcpProxyScriptFetcher
{
135 MockDhcpProxyScriptFetcher();
136 ~MockDhcpProxyScriptFetcher() override
;
138 int Fetch(base::string16
* utf16_text
,
139 const CompletionCallback
& callback
) override
;
140 void Cancel() override
;
141 const GURL
& GetPacURL() const override
;
143 virtual void SetPacURL(const GURL
& url
);
145 virtual void CompleteRequests(int result
, const base::string16
& script
);
148 CompletionCallback callback_
;
149 base::string16
* utf16_text_
;
151 DISALLOW_COPY_AND_ASSIGN(MockDhcpProxyScriptFetcher
);
154 MockDhcpProxyScriptFetcher::MockDhcpProxyScriptFetcher() { }
156 MockDhcpProxyScriptFetcher::~MockDhcpProxyScriptFetcher() { }
158 int MockDhcpProxyScriptFetcher::Fetch(base::string16
* utf16_text
,
159 const CompletionCallback
& callback
) {
160 utf16_text_
= utf16_text
;
161 callback_
= callback
;
162 return ERR_IO_PENDING
;
165 void MockDhcpProxyScriptFetcher::Cancel() { }
167 const GURL
& MockDhcpProxyScriptFetcher::GetPacURL() const {
171 void MockDhcpProxyScriptFetcher::SetPacURL(const GURL
& url
) {
175 void MockDhcpProxyScriptFetcher::CompleteRequests(
176 int result
, const base::string16
& script
) {
177 *utf16_text_
= script
;
178 callback_
.Run(result
);
181 // Succeed using custom PAC script.
182 TEST(ProxyScriptDeciderTest
, CustomPacSucceeds
) {
184 RuleBasedProxyScriptFetcher
fetcher(&rules
);
185 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
188 config
.set_pac_url(GURL("http://custom/proxy.pac"));
190 Rules::Rule rule
= rules
.AddSuccessRule("http://custom/proxy.pac");
192 TestCompletionCallback callback
;
194 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
195 EXPECT_EQ(OK
, decider
.Start(
196 config
, base::TimeDelta(), true, callback
.callback()));
197 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
199 // Check the NetLog was filled correctly.
200 TestNetLogEntry::List entries
;
201 log
.GetEntries(&entries
);
203 EXPECT_EQ(4u, entries
.size());
204 EXPECT_TRUE(LogContainsBeginEvent(
205 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
206 EXPECT_TRUE(LogContainsBeginEvent(
207 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
208 EXPECT_TRUE(LogContainsEndEvent(
209 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
210 EXPECT_TRUE(LogContainsEndEvent(
211 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
213 EXPECT_TRUE(decider
.effective_config().has_pac_url());
214 EXPECT_EQ(config
.pac_url(), decider
.effective_config().pac_url());
217 // Fail downloading the custom PAC script.
218 TEST(ProxyScriptDeciderTest
, CustomPacFails1
) {
220 RuleBasedProxyScriptFetcher
fetcher(&rules
);
221 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
224 config
.set_pac_url(GURL("http://custom/proxy.pac"));
226 rules
.AddFailDownloadRule("http://custom/proxy.pac");
228 TestCompletionCallback callback
;
230 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
231 EXPECT_EQ(kFailedDownloading
,
232 decider
.Start(config
, base::TimeDelta(), true,
233 callback
.callback()));
234 EXPECT_EQ(NULL
, decider
.script_data());
236 // Check the NetLog was filled correctly.
237 TestNetLogEntry::List entries
;
238 log
.GetEntries(&entries
);
240 EXPECT_EQ(4u, entries
.size());
241 EXPECT_TRUE(LogContainsBeginEvent(
242 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
243 EXPECT_TRUE(LogContainsBeginEvent(
244 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
245 EXPECT_TRUE(LogContainsEndEvent(
246 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
247 EXPECT_TRUE(LogContainsEndEvent(
248 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
250 EXPECT_FALSE(decider
.effective_config().has_pac_url());
253 // Fail parsing the custom PAC script.
254 TEST(ProxyScriptDeciderTest
, CustomPacFails2
) {
256 RuleBasedProxyScriptFetcher
fetcher(&rules
);
257 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
260 config
.set_pac_url(GURL("http://custom/proxy.pac"));
262 rules
.AddFailParsingRule("http://custom/proxy.pac");
264 TestCompletionCallback callback
;
265 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
266 EXPECT_EQ(kFailedParsing
,
267 decider
.Start(config
, base::TimeDelta(), true,
268 callback
.callback()));
269 EXPECT_EQ(NULL
, decider
.script_data());
272 // Fail downloading the custom PAC script, because the fetcher was NULL.
273 TEST(ProxyScriptDeciderTest
, HasNullProxyScriptFetcher
) {
275 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
278 config
.set_pac_url(GURL("http://custom/proxy.pac"));
280 TestCompletionCallback callback
;
281 ProxyScriptDecider
decider(NULL
, &dhcp_fetcher
, NULL
);
282 EXPECT_EQ(ERR_UNEXPECTED
,
283 decider
.Start(config
, base::TimeDelta(), true,
284 callback
.callback()));
285 EXPECT_EQ(NULL
, decider
.script_data());
288 // Succeeds in choosing autodetect (WPAD DNS).
289 TEST(ProxyScriptDeciderTest
, AutodetectSuccess
) {
291 RuleBasedProxyScriptFetcher
fetcher(&rules
);
292 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
295 config
.set_auto_detect(true);
297 Rules::Rule rule
= rules
.AddSuccessRule("http://wpad/wpad.dat");
299 TestCompletionCallback callback
;
300 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
301 EXPECT_EQ(OK
, decider
.Start(
302 config
, base::TimeDelta(), true, callback
.callback()));
303 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
305 EXPECT_TRUE(decider
.effective_config().has_pac_url());
306 EXPECT_EQ(rule
.url
, decider
.effective_config().pac_url());
309 class ProxyScriptDeciderQuickCheckTest
: public ::testing::Test
{
311 ProxyScriptDeciderQuickCheckTest()
312 : rule_(rules_
.AddSuccessRule("http://wpad/wpad.dat")),
313 fetcher_(&rules_
) { }
315 void SetUp() override
{
316 request_context_
.set_host_resolver(&resolver_
);
317 fetcher_
.SetRequestContext(&request_context_
);
318 config_
.set_auto_detect(true);
319 decider_
.reset(new ProxyScriptDecider(&fetcher_
, &dhcp_fetcher_
, NULL
));
323 return decider_
->Start(config_
, base::TimeDelta(), true,
324 callback_
.callback());
328 scoped_ptr
<ProxyScriptDecider
> decider_
;
329 MockHostResolver resolver_
;
332 TestCompletionCallback callback_
;
333 RuleBasedProxyScriptFetcher fetcher_
;
335 DoNothingDhcpProxyScriptFetcher dhcp_fetcher_
;
338 URLRequestContext request_context_
;
341 // Fails if a synchronous DNS lookup success for wpad causes QuickCheck to fail.
342 TEST_F(ProxyScriptDeciderQuickCheckTest
, SyncSuccess
) {
343 resolver_
.set_synchronous_mode(true);
344 resolver_
.rules()->AddRule("wpad", "1.2.3.4");
346 EXPECT_EQ(OK
, StartDecider());
347 EXPECT_EQ(rule_
.text(), decider_
->script_data()->utf16());
349 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
350 EXPECT_EQ(rule_
.url
, decider_
->effective_config().pac_url());
353 // Fails if an asynchronous DNS lookup success for wpad causes QuickCheck to
355 TEST_F(ProxyScriptDeciderQuickCheckTest
, AsyncSuccess
) {
356 resolver_
.set_ondemand_mode(true);
357 resolver_
.rules()->AddRule("wpad", "1.2.3.4");
359 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
360 ASSERT_TRUE(resolver_
.has_pending_requests());
361 resolver_
.ResolveAllPending();
362 callback_
.WaitForResult();
363 EXPECT_FALSE(resolver_
.has_pending_requests());
364 EXPECT_EQ(rule_
.text(), decider_
->script_data()->utf16());
365 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
366 EXPECT_EQ(rule_
.url
, decider_
->effective_config().pac_url());
369 // Fails if an asynchronous DNS lookup failure (i.e. an NXDOMAIN) still causes
370 // ProxyScriptDecider to yield a PAC URL.
371 TEST_F(ProxyScriptDeciderQuickCheckTest
, AsyncFail
) {
372 resolver_
.set_ondemand_mode(true);
373 resolver_
.rules()->AddSimulatedFailure("wpad");
374 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
375 ASSERT_TRUE(resolver_
.has_pending_requests());
376 resolver_
.ResolveAllPending();
377 callback_
.WaitForResult();
378 EXPECT_FALSE(decider_
->effective_config().has_pac_url());
381 // Fails if a DNS lookup timeout either causes ProxyScriptDecider to yield a PAC
382 // URL or causes ProxyScriptDecider not to cancel its pending resolution.
383 TEST_F(ProxyScriptDeciderQuickCheckTest
, AsyncTimeout
) {
384 resolver_
.set_ondemand_mode(true);
385 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
386 ASSERT_TRUE(resolver_
.has_pending_requests());
387 callback_
.WaitForResult();
388 EXPECT_FALSE(resolver_
.has_pending_requests());
389 EXPECT_FALSE(decider_
->effective_config().has_pac_url());
392 // Fails if DHCP check doesn't take place before QuickCheck.
393 TEST_F(ProxyScriptDeciderQuickCheckTest
, QuickCheckInhibitsDhcp
) {
394 MockDhcpProxyScriptFetcher dhcp_fetcher
;
395 const char *kPac
= "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
396 base::string16 pac_contents
= base::UTF8ToUTF16(kPac
);
397 GURL
url("http://foobar/baz");
398 dhcp_fetcher
.SetPacURL(url
);
399 decider_
.reset(new ProxyScriptDecider(&fetcher_
, &dhcp_fetcher
, NULL
));
400 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
401 dhcp_fetcher
.CompleteRequests(OK
, pac_contents
);
402 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
403 EXPECT_EQ(decider_
->effective_config().pac_url(), url
);
406 // Fails if QuickCheck still happens when disabled. To ensure QuickCheck is not
407 // happening, we add a synchronous failing resolver, which would ordinarily
408 // mean a QuickCheck failure, then ensure that our ProxyScriptFetcher is still
410 TEST_F(ProxyScriptDeciderQuickCheckTest
, QuickCheckDisabled
) {
411 const char *kPac
= "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
412 resolver_
.set_synchronous_mode(true);
413 resolver_
.rules()->AddSimulatedFailure("wpad");
414 MockProxyScriptFetcher fetcher
;
415 decider_
.reset(new ProxyScriptDecider(&fetcher
, &dhcp_fetcher_
, NULL
));
416 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
417 EXPECT_TRUE(fetcher
.has_pending_request());
418 fetcher
.NotifyFetchCompletion(OK
, kPac
);
421 TEST_F(ProxyScriptDeciderQuickCheckTest
, ExplicitPacUrl
) {
422 const char *kCustomUrl
= "http://custom/proxy.pac";
423 config_
.set_pac_url(GURL(kCustomUrl
));
424 Rules::Rule rule
= rules_
.AddSuccessRule(kCustomUrl
);
425 resolver_
.rules()->AddSimulatedFailure("wpad");
426 resolver_
.rules()->AddRule("custom", "1.2.3.4");
427 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
428 callback_
.WaitForResult();
429 EXPECT_TRUE(decider_
->effective_config().has_pac_url());
430 EXPECT_EQ(rule
.url
, decider_
->effective_config().pac_url());
433 // Regression test for http://crbug.com/409698.
434 // This test lets the state machine get into state QUICK_CHECK_COMPLETE, then
435 // destroys the decider, causing a cancel.
436 TEST_F(ProxyScriptDeciderQuickCheckTest
, CancelPartway
) {
437 resolver_
.set_synchronous_mode(false);
438 resolver_
.set_ondemand_mode(true);
439 EXPECT_EQ(ERR_IO_PENDING
, StartDecider());
440 decider_
.reset(NULL
);
443 // Fails at WPAD (downloading), but succeeds in choosing the custom PAC.
444 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomSuccess1
) {
446 RuleBasedProxyScriptFetcher
fetcher(&rules
);
447 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
450 config
.set_auto_detect(true);
451 config
.set_pac_url(GURL("http://custom/proxy.pac"));
453 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
454 Rules::Rule rule
= rules
.AddSuccessRule("http://custom/proxy.pac");
456 TestCompletionCallback callback
;
457 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
458 EXPECT_EQ(OK
, decider
.Start(
459 config
, base::TimeDelta(), true, callback
.callback()));
460 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
462 EXPECT_TRUE(decider
.effective_config().has_pac_url());
463 EXPECT_EQ(rule
.url
, decider
.effective_config().pac_url());
466 // Fails at WPAD (no DHCP config, DNS PAC fails parsing), but succeeds in
467 // choosing the custom PAC.
468 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomSuccess2
) {
470 RuleBasedProxyScriptFetcher
fetcher(&rules
);
471 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
474 config
.set_auto_detect(true);
475 config
.set_pac_url(GURL("http://custom/proxy.pac"));
476 config
.proxy_rules().ParseFromString("unused-manual-proxy:99");
478 rules
.AddFailParsingRule("http://wpad/wpad.dat");
479 Rules::Rule rule
= rules
.AddSuccessRule("http://custom/proxy.pac");
481 TestCompletionCallback callback
;
484 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
485 EXPECT_EQ(OK
, decider
.Start(config
, base::TimeDelta(),
486 true, callback
.callback()));
487 EXPECT_EQ(rule
.text(), decider
.script_data()->utf16());
489 // Verify that the effective configuration no longer contains auto detect or
490 // any of the manual settings.
491 EXPECT_TRUE(decider
.effective_config().Equals(
492 ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac"))));
494 // Check the NetLog was filled correctly.
495 // (Note that various states are repeated since both WPAD and custom
496 // PAC scripts are tried).
497 TestNetLogEntry::List entries
;
498 log
.GetEntries(&entries
);
500 EXPECT_EQ(10u, entries
.size());
501 EXPECT_TRUE(LogContainsBeginEvent(
502 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
503 // This is the DHCP phase, which fails fetching rather than parsing, so
504 // there is no pair of SET_PAC_SCRIPT events.
505 EXPECT_TRUE(LogContainsBeginEvent(
506 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
507 EXPECT_TRUE(LogContainsEndEvent(
508 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
509 EXPECT_TRUE(LogContainsEvent(
511 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE
,
512 NetLog::PHASE_NONE
));
513 // This is the DNS phase, which attempts a fetch but fails.
514 EXPECT_TRUE(LogContainsBeginEvent(
515 entries
, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
516 EXPECT_TRUE(LogContainsEndEvent(
517 entries
, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
518 EXPECT_TRUE(LogContainsEvent(
520 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE
,
521 NetLog::PHASE_NONE
));
522 // Finally, the custom PAC URL phase.
523 EXPECT_TRUE(LogContainsBeginEvent(
524 entries
, 7, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
525 EXPECT_TRUE(LogContainsEndEvent(
526 entries
, 8, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
527 EXPECT_TRUE(LogContainsEndEvent(
528 entries
, 9, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
531 // Fails at WPAD (downloading), and fails at custom PAC (downloading).
532 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomFails1
) {
534 RuleBasedProxyScriptFetcher
fetcher(&rules
);
535 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
538 config
.set_auto_detect(true);
539 config
.set_pac_url(GURL("http://custom/proxy.pac"));
541 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
542 rules
.AddFailDownloadRule("http://custom/proxy.pac");
544 TestCompletionCallback callback
;
545 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
546 EXPECT_EQ(kFailedDownloading
,
547 decider
.Start(config
, base::TimeDelta(), true,
548 callback
.callback()));
549 EXPECT_EQ(NULL
, decider
.script_data());
552 // Fails at WPAD (downloading), and fails at custom PAC (parsing).
553 TEST(ProxyScriptDeciderTest
, AutodetectFailCustomFails2
) {
555 RuleBasedProxyScriptFetcher
fetcher(&rules
);
556 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
559 config
.set_auto_detect(true);
560 config
.set_pac_url(GURL("http://custom/proxy.pac"));
562 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
563 rules
.AddFailParsingRule("http://custom/proxy.pac");
565 TestCompletionCallback callback
;
566 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
567 EXPECT_EQ(kFailedParsing
,
568 decider
.Start(config
, base::TimeDelta(), true,
569 callback
.callback()));
570 EXPECT_EQ(NULL
, decider
.script_data());
573 // This is a copy-paste of CustomPacFails1, with the exception that we give it
574 // a 1 millisecond delay. This means it will now complete asynchronously.
575 // Moreover, we test the NetLog to make sure it logged the pause.
576 TEST(ProxyScriptDeciderTest
, CustomPacFails1_WithPositiveDelay
) {
578 RuleBasedProxyScriptFetcher
fetcher(&rules
);
579 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
582 config
.set_pac_url(GURL("http://custom/proxy.pac"));
584 rules
.AddFailDownloadRule("http://custom/proxy.pac");
586 TestCompletionCallback callback
;
588 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
589 EXPECT_EQ(ERR_IO_PENDING
,
590 decider
.Start(config
, base::TimeDelta::FromMilliseconds(1),
591 true, callback
.callback()));
593 EXPECT_EQ(kFailedDownloading
, callback
.WaitForResult());
594 EXPECT_EQ(NULL
, decider
.script_data());
596 // Check the NetLog was filled correctly.
597 TestNetLogEntry::List entries
;
598 log
.GetEntries(&entries
);
600 EXPECT_EQ(6u, entries
.size());
601 EXPECT_TRUE(LogContainsBeginEvent(
602 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
603 EXPECT_TRUE(LogContainsBeginEvent(
604 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT
));
605 EXPECT_TRUE(LogContainsEndEvent(
606 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT
));
607 EXPECT_TRUE(LogContainsBeginEvent(
608 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
609 EXPECT_TRUE(LogContainsEndEvent(
610 entries
, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
611 EXPECT_TRUE(LogContainsEndEvent(
612 entries
, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
615 // This is a copy-paste of CustomPacFails1, with the exception that we give it
616 // a -5 second delay instead of a 0 ms delay. This change should have no effect
617 // so the rest of the test is unchanged.
618 TEST(ProxyScriptDeciderTest
, CustomPacFails1_WithNegativeDelay
) {
620 RuleBasedProxyScriptFetcher
fetcher(&rules
);
621 DoNothingDhcpProxyScriptFetcher dhcp_fetcher
;
624 config
.set_pac_url(GURL("http://custom/proxy.pac"));
626 rules
.AddFailDownloadRule("http://custom/proxy.pac");
628 TestCompletionCallback callback
;
630 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, &log
);
631 EXPECT_EQ(kFailedDownloading
,
632 decider
.Start(config
, base::TimeDelta::FromSeconds(-5),
633 true, callback
.callback()));
634 EXPECT_EQ(NULL
, decider
.script_data());
636 // Check the NetLog was filled correctly.
637 TestNetLogEntry::List entries
;
638 log
.GetEntries(&entries
);
640 EXPECT_EQ(4u, entries
.size());
641 EXPECT_TRUE(LogContainsBeginEvent(
642 entries
, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
643 EXPECT_TRUE(LogContainsBeginEvent(
644 entries
, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
645 EXPECT_TRUE(LogContainsEndEvent(
646 entries
, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT
));
647 EXPECT_TRUE(LogContainsEndEvent(
648 entries
, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER
));
651 class SynchronousSuccessDhcpFetcher
: public DhcpProxyScriptFetcher
{
653 explicit SynchronousSuccessDhcpFetcher(const base::string16
& expected_text
)
654 : gurl_("http://dhcppac/"), expected_text_(expected_text
) {
657 int Fetch(base::string16
* utf16_text
,
658 const CompletionCallback
& callback
) override
{
659 *utf16_text
= expected_text_
;
663 void Cancel() override
{}
665 const GURL
& GetPacURL() const override
{ return gurl_
; }
667 const base::string16
& expected_text() const {
668 return expected_text_
;
673 base::string16 expected_text_
;
675 DISALLOW_COPY_AND_ASSIGN(SynchronousSuccessDhcpFetcher
);
678 // All of the tests above that use ProxyScriptDecider have tested
679 // failure to fetch a PAC file via DHCP configuration, so we now test
680 // success at downloading and parsing, and then success at downloading,
681 // failure at parsing.
683 TEST(ProxyScriptDeciderTest
, AutodetectDhcpSuccess
) {
685 RuleBasedProxyScriptFetcher
fetcher(&rules
);
686 SynchronousSuccessDhcpFetcher
dhcp_fetcher(
687 base::WideToUTF16(L
"http://bingo/!FindProxyForURL"));
690 config
.set_auto_detect(true);
692 rules
.AddSuccessRule("http://bingo/");
693 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
695 TestCompletionCallback callback
;
696 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
697 EXPECT_EQ(OK
, decider
.Start(
698 config
, base::TimeDelta(), true, callback
.callback()));
699 EXPECT_EQ(dhcp_fetcher
.expected_text(),
700 decider
.script_data()->utf16());
702 EXPECT_TRUE(decider
.effective_config().has_pac_url());
703 EXPECT_EQ(GURL("http://dhcppac/"), decider
.effective_config().pac_url());
706 TEST(ProxyScriptDeciderTest
, AutodetectDhcpFailParse
) {
708 RuleBasedProxyScriptFetcher
fetcher(&rules
);
709 SynchronousSuccessDhcpFetcher
dhcp_fetcher(
710 base::WideToUTF16(L
"http://bingo/!invalid-script"));
713 config
.set_auto_detect(true);
715 rules
.AddFailParsingRule("http://bingo/");
716 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
718 TestCompletionCallback callback
;
719 ProxyScriptDecider
decider(&fetcher
, &dhcp_fetcher
, NULL
);
720 // Since there is fallback to DNS-based WPAD, the final error will be that
721 // it failed downloading, not that it failed parsing.
722 EXPECT_EQ(kFailedDownloading
,
723 decider
.Start(config
, base::TimeDelta(), true, callback
.callback()));
724 EXPECT_EQ(NULL
, decider
.script_data());
726 EXPECT_FALSE(decider
.effective_config().has_pac_url());
729 class AsyncFailDhcpFetcher
730 : public DhcpProxyScriptFetcher
,
731 public base::SupportsWeakPtr
<AsyncFailDhcpFetcher
> {
733 AsyncFailDhcpFetcher() {}
734 ~AsyncFailDhcpFetcher() override
{}
736 int Fetch(base::string16
* utf16_text
,
737 const CompletionCallback
& callback
) override
{
738 callback_
= callback
;
739 base::MessageLoop::current()->PostTask(
741 base::Bind(&AsyncFailDhcpFetcher::CallbackWithFailure
, AsWeakPtr()));
742 return ERR_IO_PENDING
;
745 void Cancel() override
{ callback_
.Reset(); }
747 const GURL
& GetPacURL() const override
{ return dummy_gurl_
; }
749 void CallbackWithFailure() {
750 if (!callback_
.is_null())
751 callback_
.Run(ERR_PAC_NOT_IN_DHCP
);
756 CompletionCallback callback_
;
759 TEST(ProxyScriptDeciderTest
, DhcpCancelledByDestructor
) {
760 // This regression test would crash before
761 // http://codereview.chromium.org/7044058/
762 // Thus, we don't care much about actual results (hence no EXPECT or ASSERT
763 // macros below), just that it doesn't crash.
765 RuleBasedProxyScriptFetcher
fetcher(&rules
);
767 scoped_ptr
<AsyncFailDhcpFetcher
> dhcp_fetcher(new AsyncFailDhcpFetcher());
770 config
.set_auto_detect(true);
771 rules
.AddFailDownloadRule("http://wpad/wpad.dat");
773 TestCompletionCallback callback
;
775 // Scope so ProxyScriptDecider gets destroyed early.
777 ProxyScriptDecider
decider(&fetcher
, dhcp_fetcher
.get(), NULL
);
778 decider
.Start(config
, base::TimeDelta(), true, callback
.callback());
781 // Run the message loop to let the DHCP fetch complete and post the results
782 // back. Before the fix linked to above, this would try to invoke on
783 // the callback object provided by ProxyScriptDecider after it was
785 base::MessageLoop::current()->RunUntilIdle();