Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / proxy / proxy_script_decider_unittest.cc
blob1c3264fe8cc689ffe4f901547e1f01857139d042
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 <vector>
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/time/time.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/dns/mock_host_resolver.h"
20 #include "net/log/net_log.h"
21 #include "net/log/test_net_log.h"
22 #include "net/log/test_net_log_entry.h"
23 #include "net/log/test_net_log_util.h"
24 #include "net/proxy/dhcp_proxy_script_fetcher.h"
25 #include "net/proxy/mock_proxy_script_fetcher.h"
26 #include "net/proxy/proxy_config.h"
27 #include "net/proxy/proxy_resolver.h"
28 #include "net/proxy/proxy_script_decider.h"
29 #include "net/proxy/proxy_script_fetcher.h"
30 #include "net/url_request/url_request_context.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 namespace net {
34 namespace {
36 enum Error {
37 kFailedDownloading = -100,
38 kFailedParsing = ERR_PAC_SCRIPT_FAILED,
41 class Rules {
42 public:
43 struct Rule {
44 Rule(const GURL& url, int fetch_error, bool is_valid_script)
45 : url(url),
46 fetch_error(fetch_error),
47 is_valid_script(is_valid_script) {
50 base::string16 text() const {
51 if (is_valid_script)
52 return base::UTF8ToUTF16(url.spec() + "!FindProxyForURL");
53 if (fetch_error == OK)
54 return base::UTF8ToUTF16(url.spec() + "!invalid-script");
55 return base::string16();
58 GURL url;
59 int fetch_error;
60 bool is_valid_script;
63 Rule AddSuccessRule(const char* url) {
64 Rule rule(GURL(url), OK /*fetch_error*/, true);
65 rules_.push_back(rule);
66 return rule;
69 void AddFailDownloadRule(const char* url) {
70 rules_.push_back(Rule(GURL(url), kFailedDownloading /*fetch_error*/,
71 false));
74 void AddFailParsingRule(const char* url) {
75 rules_.push_back(Rule(GURL(url), OK /*fetch_error*/, false));
78 const Rule& GetRuleByUrl(const GURL& url) const {
79 for (RuleList::const_iterator it = rules_.begin(); it != rules_.end();
80 ++it) {
81 if (it->url == url)
82 return *it;
84 LOG(FATAL) << "Rule not found for " << url;
85 return rules_[0];
88 const Rule& GetRuleByText(const base::string16& text) const {
89 for (RuleList::const_iterator it = rules_.begin(); it != rules_.end();
90 ++it) {
91 if (it->text() == text)
92 return *it;
94 LOG(FATAL) << "Rule not found for " << text;
95 return rules_[0];
98 private:
99 typedef std::vector<Rule> RuleList;
100 RuleList rules_;
103 class RuleBasedProxyScriptFetcher : public ProxyScriptFetcher {
104 public:
105 explicit RuleBasedProxyScriptFetcher(const Rules* rules)
106 : rules_(rules), request_context_(NULL) {}
108 virtual void SetRequestContext(URLRequestContext* context) {
109 request_context_ = context;
112 // ProxyScriptFetcher implementation.
113 int Fetch(const GURL& url,
114 base::string16* text,
115 const CompletionCallback& callback) override {
116 const Rules::Rule& rule = rules_->GetRuleByUrl(url);
117 int rv = rule.fetch_error;
118 EXPECT_NE(ERR_UNEXPECTED, rv);
119 if (rv == OK)
120 *text = rule.text();
121 return rv;
124 void Cancel() override {}
126 URLRequestContext* GetRequestContext() const override {
127 return request_context_;
130 private:
131 const Rules* rules_;
132 URLRequestContext* request_context_;
135 // A mock retriever, returns asynchronously when CompleteRequests() is called.
136 class MockDhcpProxyScriptFetcher : public DhcpProxyScriptFetcher {
137 public:
138 MockDhcpProxyScriptFetcher();
139 ~MockDhcpProxyScriptFetcher() override;
141 int Fetch(base::string16* utf16_text,
142 const CompletionCallback& callback) override;
143 void Cancel() override;
144 const GURL& GetPacURL() const override;
146 virtual void SetPacURL(const GURL& url);
148 virtual void CompleteRequests(int result, const base::string16& script);
150 private:
151 CompletionCallback callback_;
152 base::string16* utf16_text_;
153 GURL gurl_;
154 DISALLOW_COPY_AND_ASSIGN(MockDhcpProxyScriptFetcher);
157 MockDhcpProxyScriptFetcher::MockDhcpProxyScriptFetcher() { }
159 MockDhcpProxyScriptFetcher::~MockDhcpProxyScriptFetcher() { }
161 int MockDhcpProxyScriptFetcher::Fetch(base::string16* utf16_text,
162 const CompletionCallback& callback) {
163 utf16_text_ = utf16_text;
164 callback_ = callback;
165 return ERR_IO_PENDING;
168 void MockDhcpProxyScriptFetcher::Cancel() { }
170 const GURL& MockDhcpProxyScriptFetcher::GetPacURL() const {
171 return gurl_;
174 void MockDhcpProxyScriptFetcher::SetPacURL(const GURL& url) {
175 gurl_ = url;
178 void MockDhcpProxyScriptFetcher::CompleteRequests(
179 int result, const base::string16& script) {
180 *utf16_text_ = script;
181 callback_.Run(result);
184 // Succeed using custom PAC script.
185 TEST(ProxyScriptDeciderTest, CustomPacSucceeds) {
186 Rules rules;
187 RuleBasedProxyScriptFetcher fetcher(&rules);
188 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
190 ProxyConfig config;
191 config.set_pac_url(GURL("http://custom/proxy.pac"));
193 Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
195 TestCompletionCallback callback;
196 TestNetLog log;
197 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
198 EXPECT_EQ(OK, decider.Start(
199 config, base::TimeDelta(), true, callback.callback()));
200 EXPECT_EQ(rule.text(), decider.script_data()->utf16());
202 // Check the NetLog was filled correctly.
203 TestNetLogEntry::List entries;
204 log.GetEntries(&entries);
206 EXPECT_EQ(4u, entries.size());
207 EXPECT_TRUE(LogContainsBeginEvent(
208 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
209 EXPECT_TRUE(LogContainsBeginEvent(
210 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
211 EXPECT_TRUE(LogContainsEndEvent(
212 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
213 EXPECT_TRUE(LogContainsEndEvent(
214 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
216 EXPECT_TRUE(decider.effective_config().has_pac_url());
217 EXPECT_EQ(config.pac_url(), decider.effective_config().pac_url());
220 // Fail downloading the custom PAC script.
221 TEST(ProxyScriptDeciderTest, CustomPacFails1) {
222 Rules rules;
223 RuleBasedProxyScriptFetcher fetcher(&rules);
224 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
226 ProxyConfig config;
227 config.set_pac_url(GURL("http://custom/proxy.pac"));
229 rules.AddFailDownloadRule("http://custom/proxy.pac");
231 TestCompletionCallback callback;
232 TestNetLog log;
233 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
234 EXPECT_EQ(kFailedDownloading,
235 decider.Start(config, base::TimeDelta(), true,
236 callback.callback()));
237 EXPECT_EQ(NULL, decider.script_data());
239 // Check the NetLog was filled correctly.
240 TestNetLogEntry::List entries;
241 log.GetEntries(&entries);
243 EXPECT_EQ(4u, entries.size());
244 EXPECT_TRUE(LogContainsBeginEvent(
245 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
246 EXPECT_TRUE(LogContainsBeginEvent(
247 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
248 EXPECT_TRUE(LogContainsEndEvent(
249 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
250 EXPECT_TRUE(LogContainsEndEvent(
251 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
253 EXPECT_FALSE(decider.effective_config().has_pac_url());
256 // Fail parsing the custom PAC script.
257 TEST(ProxyScriptDeciderTest, CustomPacFails2) {
258 Rules rules;
259 RuleBasedProxyScriptFetcher fetcher(&rules);
260 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
262 ProxyConfig config;
263 config.set_pac_url(GURL("http://custom/proxy.pac"));
265 rules.AddFailParsingRule("http://custom/proxy.pac");
267 TestCompletionCallback callback;
268 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
269 EXPECT_EQ(kFailedParsing,
270 decider.Start(config, base::TimeDelta(), true,
271 callback.callback()));
272 EXPECT_EQ(NULL, decider.script_data());
275 // Fail downloading the custom PAC script, because the fetcher was NULL.
276 TEST(ProxyScriptDeciderTest, HasNullProxyScriptFetcher) {
277 Rules rules;
278 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
280 ProxyConfig config;
281 config.set_pac_url(GURL("http://custom/proxy.pac"));
283 TestCompletionCallback callback;
284 ProxyScriptDecider decider(NULL, &dhcp_fetcher, NULL);
285 EXPECT_EQ(ERR_UNEXPECTED,
286 decider.Start(config, base::TimeDelta(), true,
287 callback.callback()));
288 EXPECT_EQ(NULL, decider.script_data());
291 // Succeeds in choosing autodetect (WPAD DNS).
292 TEST(ProxyScriptDeciderTest, AutodetectSuccess) {
293 Rules rules;
294 RuleBasedProxyScriptFetcher fetcher(&rules);
295 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
297 ProxyConfig config;
298 config.set_auto_detect(true);
300 Rules::Rule rule = rules.AddSuccessRule("http://wpad/wpad.dat");
302 TestCompletionCallback callback;
303 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
304 EXPECT_EQ(OK, decider.Start(
305 config, base::TimeDelta(), true, callback.callback()));
306 EXPECT_EQ(rule.text(), decider.script_data()->utf16());
308 EXPECT_TRUE(decider.effective_config().has_pac_url());
309 EXPECT_EQ(rule.url, decider.effective_config().pac_url());
312 class ProxyScriptDeciderQuickCheckTest : public ::testing::Test {
313 public:
314 ProxyScriptDeciderQuickCheckTest()
315 : rule_(rules_.AddSuccessRule("http://wpad/wpad.dat")),
316 fetcher_(&rules_) { }
318 void SetUp() override {
319 request_context_.set_host_resolver(&resolver_);
320 fetcher_.SetRequestContext(&request_context_);
321 config_.set_auto_detect(true);
322 decider_.reset(new ProxyScriptDecider(&fetcher_, &dhcp_fetcher_, NULL));
325 int StartDecider() {
326 return decider_->Start(config_, base::TimeDelta(), true,
327 callback_.callback());
330 protected:
331 scoped_ptr<ProxyScriptDecider> decider_;
332 MockHostResolver resolver_;
333 Rules rules_;
334 Rules::Rule rule_;
335 TestCompletionCallback callback_;
336 RuleBasedProxyScriptFetcher fetcher_;
337 ProxyConfig config_;
338 DoNothingDhcpProxyScriptFetcher dhcp_fetcher_;
340 private:
341 URLRequestContext request_context_;
344 // Fails if a synchronous DNS lookup success for wpad causes QuickCheck to fail.
345 TEST_F(ProxyScriptDeciderQuickCheckTest, SyncSuccess) {
346 resolver_.set_synchronous_mode(true);
347 resolver_.rules()->AddRule("wpad", "1.2.3.4");
349 EXPECT_EQ(OK, StartDecider());
350 EXPECT_EQ(rule_.text(), decider_->script_data()->utf16());
352 EXPECT_TRUE(decider_->effective_config().has_pac_url());
353 EXPECT_EQ(rule_.url, decider_->effective_config().pac_url());
356 // Fails if an asynchronous DNS lookup success for wpad causes QuickCheck to
357 // fail.
358 TEST_F(ProxyScriptDeciderQuickCheckTest, AsyncSuccess) {
359 resolver_.set_ondemand_mode(true);
360 resolver_.rules()->AddRule("wpad", "1.2.3.4");
362 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
363 ASSERT_TRUE(resolver_.has_pending_requests());
364 resolver_.ResolveAllPending();
365 callback_.WaitForResult();
366 EXPECT_FALSE(resolver_.has_pending_requests());
367 EXPECT_EQ(rule_.text(), decider_->script_data()->utf16());
368 EXPECT_TRUE(decider_->effective_config().has_pac_url());
369 EXPECT_EQ(rule_.url, decider_->effective_config().pac_url());
372 // Fails if an asynchronous DNS lookup failure (i.e. an NXDOMAIN) still causes
373 // ProxyScriptDecider to yield a PAC URL.
374 TEST_F(ProxyScriptDeciderQuickCheckTest, AsyncFail) {
375 resolver_.set_ondemand_mode(true);
376 resolver_.rules()->AddSimulatedFailure("wpad");
377 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
378 ASSERT_TRUE(resolver_.has_pending_requests());
379 resolver_.ResolveAllPending();
380 callback_.WaitForResult();
381 EXPECT_FALSE(decider_->effective_config().has_pac_url());
384 // Fails if a DNS lookup timeout either causes ProxyScriptDecider to yield a PAC
385 // URL or causes ProxyScriptDecider not to cancel its pending resolution.
386 TEST_F(ProxyScriptDeciderQuickCheckTest, AsyncTimeout) {
387 resolver_.set_ondemand_mode(true);
388 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
389 ASSERT_TRUE(resolver_.has_pending_requests());
390 callback_.WaitForResult();
391 EXPECT_FALSE(resolver_.has_pending_requests());
392 EXPECT_FALSE(decider_->effective_config().has_pac_url());
395 // Fails if DHCP check doesn't take place before QuickCheck.
396 TEST_F(ProxyScriptDeciderQuickCheckTest, QuickCheckInhibitsDhcp) {
397 MockDhcpProxyScriptFetcher dhcp_fetcher;
398 const char *kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
399 base::string16 pac_contents = base::UTF8ToUTF16(kPac);
400 GURL url("http://foobar/baz");
401 dhcp_fetcher.SetPacURL(url);
402 decider_.reset(new ProxyScriptDecider(&fetcher_, &dhcp_fetcher, NULL));
403 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
404 dhcp_fetcher.CompleteRequests(OK, pac_contents);
405 EXPECT_TRUE(decider_->effective_config().has_pac_url());
406 EXPECT_EQ(decider_->effective_config().pac_url(), url);
409 // Fails if QuickCheck still happens when disabled. To ensure QuickCheck is not
410 // happening, we add a synchronous failing resolver, which would ordinarily
411 // mean a QuickCheck failure, then ensure that our ProxyScriptFetcher is still
412 // asked to fetch.
413 TEST_F(ProxyScriptDeciderQuickCheckTest, QuickCheckDisabled) {
414 const char *kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
415 resolver_.set_synchronous_mode(true);
416 resolver_.rules()->AddSimulatedFailure("wpad");
417 MockProxyScriptFetcher fetcher;
418 decider_.reset(new ProxyScriptDecider(&fetcher, &dhcp_fetcher_, NULL));
419 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
420 EXPECT_TRUE(fetcher.has_pending_request());
421 fetcher.NotifyFetchCompletion(OK, kPac);
424 TEST_F(ProxyScriptDeciderQuickCheckTest, ExplicitPacUrl) {
425 const char *kCustomUrl = "http://custom/proxy.pac";
426 config_.set_pac_url(GURL(kCustomUrl));
427 Rules::Rule rule = rules_.AddSuccessRule(kCustomUrl);
428 resolver_.rules()->AddSimulatedFailure("wpad");
429 resolver_.rules()->AddRule("custom", "1.2.3.4");
430 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
431 callback_.WaitForResult();
432 EXPECT_TRUE(decider_->effective_config().has_pac_url());
433 EXPECT_EQ(rule.url, decider_->effective_config().pac_url());
436 // Regression test for http://crbug.com/409698.
437 // This test lets the state machine get into state QUICK_CHECK_COMPLETE, then
438 // destroys the decider, causing a cancel.
439 TEST_F(ProxyScriptDeciderQuickCheckTest, CancelPartway) {
440 resolver_.set_synchronous_mode(false);
441 resolver_.set_ondemand_mode(true);
442 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
443 decider_.reset(NULL);
446 // Fails at WPAD (downloading), but succeeds in choosing the custom PAC.
447 TEST(ProxyScriptDeciderTest, AutodetectFailCustomSuccess1) {
448 Rules rules;
449 RuleBasedProxyScriptFetcher fetcher(&rules);
450 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
452 ProxyConfig config;
453 config.set_auto_detect(true);
454 config.set_pac_url(GURL("http://custom/proxy.pac"));
456 rules.AddFailDownloadRule("http://wpad/wpad.dat");
457 Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
459 TestCompletionCallback callback;
460 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
461 EXPECT_EQ(OK, decider.Start(
462 config, base::TimeDelta(), true, callback.callback()));
463 EXPECT_EQ(rule.text(), decider.script_data()->utf16());
465 EXPECT_TRUE(decider.effective_config().has_pac_url());
466 EXPECT_EQ(rule.url, decider.effective_config().pac_url());
469 // Fails at WPAD (no DHCP config, DNS PAC fails parsing), but succeeds in
470 // choosing the custom PAC.
471 TEST(ProxyScriptDeciderTest, AutodetectFailCustomSuccess2) {
472 Rules rules;
473 RuleBasedProxyScriptFetcher fetcher(&rules);
474 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
476 ProxyConfig config;
477 config.set_auto_detect(true);
478 config.set_pac_url(GURL("http://custom/proxy.pac"));
479 config.proxy_rules().ParseFromString("unused-manual-proxy:99");
481 rules.AddFailParsingRule("http://wpad/wpad.dat");
482 Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
484 TestCompletionCallback callback;
485 TestNetLog log;
487 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
488 EXPECT_EQ(OK, decider.Start(config, base::TimeDelta(),
489 true, callback.callback()));
490 EXPECT_EQ(rule.text(), decider.script_data()->utf16());
492 // Verify that the effective configuration no longer contains auto detect or
493 // any of the manual settings.
494 EXPECT_TRUE(decider.effective_config().Equals(
495 ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac"))));
497 // Check the NetLog was filled correctly.
498 // (Note that various states are repeated since both WPAD and custom
499 // PAC scripts are tried).
500 TestNetLogEntry::List entries;
501 log.GetEntries(&entries);
503 EXPECT_EQ(10u, entries.size());
504 EXPECT_TRUE(LogContainsBeginEvent(
505 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
506 // This is the DHCP phase, which fails fetching rather than parsing, so
507 // there is no pair of SET_PAC_SCRIPT events.
508 EXPECT_TRUE(LogContainsBeginEvent(
509 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
510 EXPECT_TRUE(LogContainsEndEvent(
511 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
512 EXPECT_TRUE(LogContainsEvent(
513 entries, 3,
514 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
515 NetLog::PHASE_NONE));
516 // This is the DNS phase, which attempts a fetch but fails.
517 EXPECT_TRUE(LogContainsBeginEvent(
518 entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
519 EXPECT_TRUE(LogContainsEndEvent(
520 entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
521 EXPECT_TRUE(LogContainsEvent(
522 entries, 6,
523 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
524 NetLog::PHASE_NONE));
525 // Finally, the custom PAC URL phase.
526 EXPECT_TRUE(LogContainsBeginEvent(
527 entries, 7, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
528 EXPECT_TRUE(LogContainsEndEvent(
529 entries, 8, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
530 EXPECT_TRUE(LogContainsEndEvent(
531 entries, 9, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
534 // Fails at WPAD (downloading), and fails at custom PAC (downloading).
535 TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails1) {
536 Rules rules;
537 RuleBasedProxyScriptFetcher fetcher(&rules);
538 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
540 ProxyConfig config;
541 config.set_auto_detect(true);
542 config.set_pac_url(GURL("http://custom/proxy.pac"));
544 rules.AddFailDownloadRule("http://wpad/wpad.dat");
545 rules.AddFailDownloadRule("http://custom/proxy.pac");
547 TestCompletionCallback callback;
548 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
549 EXPECT_EQ(kFailedDownloading,
550 decider.Start(config, base::TimeDelta(), true,
551 callback.callback()));
552 EXPECT_EQ(NULL, decider.script_data());
555 // Fails at WPAD (downloading), and fails at custom PAC (parsing).
556 TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails2) {
557 Rules rules;
558 RuleBasedProxyScriptFetcher fetcher(&rules);
559 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
561 ProxyConfig config;
562 config.set_auto_detect(true);
563 config.set_pac_url(GURL("http://custom/proxy.pac"));
565 rules.AddFailDownloadRule("http://wpad/wpad.dat");
566 rules.AddFailParsingRule("http://custom/proxy.pac");
568 TestCompletionCallback callback;
569 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
570 EXPECT_EQ(kFailedParsing,
571 decider.Start(config, base::TimeDelta(), true,
572 callback.callback()));
573 EXPECT_EQ(NULL, decider.script_data());
576 // This is a copy-paste of CustomPacFails1, with the exception that we give it
577 // a 1 millisecond delay. This means it will now complete asynchronously.
578 // Moreover, we test the NetLog to make sure it logged the pause.
579 TEST(ProxyScriptDeciderTest, CustomPacFails1_WithPositiveDelay) {
580 Rules rules;
581 RuleBasedProxyScriptFetcher fetcher(&rules);
582 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
584 ProxyConfig config;
585 config.set_pac_url(GURL("http://custom/proxy.pac"));
587 rules.AddFailDownloadRule("http://custom/proxy.pac");
589 TestCompletionCallback callback;
590 TestNetLog log;
591 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
592 EXPECT_EQ(ERR_IO_PENDING,
593 decider.Start(config, base::TimeDelta::FromMilliseconds(1),
594 true, callback.callback()));
596 EXPECT_EQ(kFailedDownloading, callback.WaitForResult());
597 EXPECT_EQ(NULL, decider.script_data());
599 // Check the NetLog was filled correctly.
600 TestNetLogEntry::List entries;
601 log.GetEntries(&entries);
603 EXPECT_EQ(6u, entries.size());
604 EXPECT_TRUE(LogContainsBeginEvent(
605 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
606 EXPECT_TRUE(LogContainsBeginEvent(
607 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT));
608 EXPECT_TRUE(LogContainsEndEvent(
609 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT));
610 EXPECT_TRUE(LogContainsBeginEvent(
611 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
612 EXPECT_TRUE(LogContainsEndEvent(
613 entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
614 EXPECT_TRUE(LogContainsEndEvent(
615 entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
618 // This is a copy-paste of CustomPacFails1, with the exception that we give it
619 // a -5 second delay instead of a 0 ms delay. This change should have no effect
620 // so the rest of the test is unchanged.
621 TEST(ProxyScriptDeciderTest, CustomPacFails1_WithNegativeDelay) {
622 Rules rules;
623 RuleBasedProxyScriptFetcher fetcher(&rules);
624 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
626 ProxyConfig config;
627 config.set_pac_url(GURL("http://custom/proxy.pac"));
629 rules.AddFailDownloadRule("http://custom/proxy.pac");
631 TestCompletionCallback callback;
632 TestNetLog log;
633 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
634 EXPECT_EQ(kFailedDownloading,
635 decider.Start(config, base::TimeDelta::FromSeconds(-5),
636 true, callback.callback()));
637 EXPECT_EQ(NULL, decider.script_data());
639 // Check the NetLog was filled correctly.
640 TestNetLogEntry::List entries;
641 log.GetEntries(&entries);
643 EXPECT_EQ(4u, entries.size());
644 EXPECT_TRUE(LogContainsBeginEvent(
645 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
646 EXPECT_TRUE(LogContainsBeginEvent(
647 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
648 EXPECT_TRUE(LogContainsEndEvent(
649 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
650 EXPECT_TRUE(LogContainsEndEvent(
651 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
654 class SynchronousSuccessDhcpFetcher : public DhcpProxyScriptFetcher {
655 public:
656 explicit SynchronousSuccessDhcpFetcher(const base::string16& expected_text)
657 : gurl_("http://dhcppac/"), expected_text_(expected_text) {
660 int Fetch(base::string16* utf16_text,
661 const CompletionCallback& callback) override {
662 *utf16_text = expected_text_;
663 return OK;
666 void Cancel() override {}
668 const GURL& GetPacURL() const override { return gurl_; }
670 const base::string16& expected_text() const {
671 return expected_text_;
674 private:
675 GURL gurl_;
676 base::string16 expected_text_;
678 DISALLOW_COPY_AND_ASSIGN(SynchronousSuccessDhcpFetcher);
681 // All of the tests above that use ProxyScriptDecider have tested
682 // failure to fetch a PAC file via DHCP configuration, so we now test
683 // success at downloading and parsing, and then success at downloading,
684 // failure at parsing.
686 TEST(ProxyScriptDeciderTest, AutodetectDhcpSuccess) {
687 Rules rules;
688 RuleBasedProxyScriptFetcher fetcher(&rules);
689 SynchronousSuccessDhcpFetcher dhcp_fetcher(
690 base::WideToUTF16(L"http://bingo/!FindProxyForURL"));
692 ProxyConfig config;
693 config.set_auto_detect(true);
695 rules.AddSuccessRule("http://bingo/");
696 rules.AddFailDownloadRule("http://wpad/wpad.dat");
698 TestCompletionCallback callback;
699 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
700 EXPECT_EQ(OK, decider.Start(
701 config, base::TimeDelta(), true, callback.callback()));
702 EXPECT_EQ(dhcp_fetcher.expected_text(),
703 decider.script_data()->utf16());
705 EXPECT_TRUE(decider.effective_config().has_pac_url());
706 EXPECT_EQ(GURL("http://dhcppac/"), decider.effective_config().pac_url());
709 TEST(ProxyScriptDeciderTest, AutodetectDhcpFailParse) {
710 Rules rules;
711 RuleBasedProxyScriptFetcher fetcher(&rules);
712 SynchronousSuccessDhcpFetcher dhcp_fetcher(
713 base::WideToUTF16(L"http://bingo/!invalid-script"));
715 ProxyConfig config;
716 config.set_auto_detect(true);
718 rules.AddFailParsingRule("http://bingo/");
719 rules.AddFailDownloadRule("http://wpad/wpad.dat");
721 TestCompletionCallback callback;
722 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
723 // Since there is fallback to DNS-based WPAD, the final error will be that
724 // it failed downloading, not that it failed parsing.
725 EXPECT_EQ(kFailedDownloading,
726 decider.Start(config, base::TimeDelta(), true, callback.callback()));
727 EXPECT_EQ(NULL, decider.script_data());
729 EXPECT_FALSE(decider.effective_config().has_pac_url());
732 class AsyncFailDhcpFetcher
733 : public DhcpProxyScriptFetcher,
734 public base::SupportsWeakPtr<AsyncFailDhcpFetcher> {
735 public:
736 AsyncFailDhcpFetcher() {}
737 ~AsyncFailDhcpFetcher() override {}
739 int Fetch(base::string16* utf16_text,
740 const CompletionCallback& callback) override {
741 callback_ = callback;
742 base::ThreadTaskRunnerHandle::Get()->PostTask(
743 FROM_HERE,
744 base::Bind(&AsyncFailDhcpFetcher::CallbackWithFailure, AsWeakPtr()));
745 return ERR_IO_PENDING;
748 void Cancel() override { callback_.Reset(); }
750 const GURL& GetPacURL() const override { return dummy_gurl_; }
752 void CallbackWithFailure() {
753 if (!callback_.is_null())
754 callback_.Run(ERR_PAC_NOT_IN_DHCP);
757 private:
758 GURL dummy_gurl_;
759 CompletionCallback callback_;
762 TEST(ProxyScriptDeciderTest, DhcpCancelledByDestructor) {
763 // This regression test would crash before
764 // http://codereview.chromium.org/7044058/
765 // Thus, we don't care much about actual results (hence no EXPECT or ASSERT
766 // macros below), just that it doesn't crash.
767 Rules rules;
768 RuleBasedProxyScriptFetcher fetcher(&rules);
770 scoped_ptr<AsyncFailDhcpFetcher> dhcp_fetcher(new AsyncFailDhcpFetcher());
772 ProxyConfig config;
773 config.set_auto_detect(true);
774 rules.AddFailDownloadRule("http://wpad/wpad.dat");
776 TestCompletionCallback callback;
778 // Scope so ProxyScriptDecider gets destroyed early.
780 ProxyScriptDecider decider(&fetcher, dhcp_fetcher.get(), NULL);
781 decider.Start(config, base::TimeDelta(), true, callback.callback());
784 // Run the message loop to let the DHCP fetch complete and post the results
785 // back. Before the fix linked to above, this would try to invoke on
786 // the callback object provided by ProxyScriptDecider after it was
787 // no longer valid.
788 base::MessageLoop::current()->RunUntilIdle();
791 } // namespace
792 } // namespace net