[Sync] Finish transition to new AndroidSyncSettings interface.
[chromium-blink-merge.git] / net / proxy / proxy_script_decider_unittest.cc
blob45f5199a2d8a13c551855e059aebc9d8cfd09247
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/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"
30 namespace net {
31 namespace {
33 enum Error {
34 kFailedDownloading = -100,
35 kFailedParsing = ERR_PAC_SCRIPT_FAILED,
38 class Rules {
39 public:
40 struct Rule {
41 Rule(const GURL& url, int fetch_error, bool is_valid_script)
42 : url(url),
43 fetch_error(fetch_error),
44 is_valid_script(is_valid_script) {
47 base::string16 text() const {
48 if (is_valid_script)
49 return base::UTF8ToUTF16(url.spec() + "!FindProxyForURL");
50 if (fetch_error == OK)
51 return base::UTF8ToUTF16(url.spec() + "!invalid-script");
52 return base::string16();
55 GURL url;
56 int fetch_error;
57 bool is_valid_script;
60 Rule AddSuccessRule(const char* url) {
61 Rule rule(GURL(url), OK /*fetch_error*/, true);
62 rules_.push_back(rule);
63 return rule;
66 void AddFailDownloadRule(const char* url) {
67 rules_.push_back(Rule(GURL(url), kFailedDownloading /*fetch_error*/,
68 false));
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();
77 ++it) {
78 if (it->url == url)
79 return *it;
81 LOG(FATAL) << "Rule not found for " << url;
82 return rules_[0];
85 const Rule& GetRuleByText(const base::string16& text) const {
86 for (RuleList::const_iterator it = rules_.begin(); it != rules_.end();
87 ++it) {
88 if (it->text() == text)
89 return *it;
91 LOG(FATAL) << "Rule not found for " << text;
92 return rules_[0];
95 private:
96 typedef std::vector<Rule> RuleList;
97 RuleList rules_;
100 class RuleBasedProxyScriptFetcher : public ProxyScriptFetcher {
101 public:
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);
116 if (rv == OK)
117 *text = rule.text();
118 return rv;
121 void Cancel() override {}
123 URLRequestContext* GetRequestContext() const override {
124 return request_context_;
127 private:
128 const Rules* rules_;
129 URLRequestContext* request_context_;
132 // A mock retriever, returns asynchronously when CompleteRequests() is called.
133 class MockDhcpProxyScriptFetcher : public DhcpProxyScriptFetcher {
134 public:
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);
147 private:
148 CompletionCallback callback_;
149 base::string16* utf16_text_;
150 GURL gurl_;
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 {
168 return gurl_;
171 void MockDhcpProxyScriptFetcher::SetPacURL(const GURL& url) {
172 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) {
183 Rules rules;
184 RuleBasedProxyScriptFetcher fetcher(&rules);
185 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
187 ProxyConfig config;
188 config.set_pac_url(GURL("http://custom/proxy.pac"));
190 Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
192 TestCompletionCallback callback;
193 TestNetLog log;
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) {
219 Rules rules;
220 RuleBasedProxyScriptFetcher fetcher(&rules);
221 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
223 ProxyConfig config;
224 config.set_pac_url(GURL("http://custom/proxy.pac"));
226 rules.AddFailDownloadRule("http://custom/proxy.pac");
228 TestCompletionCallback callback;
229 TestNetLog log;
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) {
255 Rules rules;
256 RuleBasedProxyScriptFetcher fetcher(&rules);
257 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
259 ProxyConfig config;
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) {
274 Rules rules;
275 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
277 ProxyConfig config;
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) {
290 Rules rules;
291 RuleBasedProxyScriptFetcher fetcher(&rules);
292 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
294 ProxyConfig config;
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 {
310 public:
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));
322 int StartDecider() {
323 return decider_->Start(config_, base::TimeDelta(), true,
324 callback_.callback());
327 protected:
328 scoped_ptr<ProxyScriptDecider> decider_;
329 MockHostResolver resolver_;
330 Rules rules_;
331 Rules::Rule rule_;
332 TestCompletionCallback callback_;
333 RuleBasedProxyScriptFetcher fetcher_;
334 ProxyConfig config_;
335 DoNothingDhcpProxyScriptFetcher dhcp_fetcher_;
337 private:
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
354 // fail.
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
409 // asked to fetch.
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) {
445 Rules rules;
446 RuleBasedProxyScriptFetcher fetcher(&rules);
447 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
449 ProxyConfig config;
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) {
469 Rules rules;
470 RuleBasedProxyScriptFetcher fetcher(&rules);
471 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
473 ProxyConfig config;
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;
482 TestNetLog log;
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(
510 entries, 3,
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(
519 entries, 6,
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) {
533 Rules rules;
534 RuleBasedProxyScriptFetcher fetcher(&rules);
535 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
537 ProxyConfig config;
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) {
554 Rules rules;
555 RuleBasedProxyScriptFetcher fetcher(&rules);
556 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
558 ProxyConfig config;
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) {
577 Rules rules;
578 RuleBasedProxyScriptFetcher fetcher(&rules);
579 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
581 ProxyConfig config;
582 config.set_pac_url(GURL("http://custom/proxy.pac"));
584 rules.AddFailDownloadRule("http://custom/proxy.pac");
586 TestCompletionCallback callback;
587 TestNetLog log;
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) {
619 Rules rules;
620 RuleBasedProxyScriptFetcher fetcher(&rules);
621 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
623 ProxyConfig config;
624 config.set_pac_url(GURL("http://custom/proxy.pac"));
626 rules.AddFailDownloadRule("http://custom/proxy.pac");
628 TestCompletionCallback callback;
629 TestNetLog log;
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 {
652 public:
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_;
660 return OK;
663 void Cancel() override {}
665 const GURL& GetPacURL() const override { return gurl_; }
667 const base::string16& expected_text() const {
668 return expected_text_;
671 private:
672 GURL gurl_;
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) {
684 Rules rules;
685 RuleBasedProxyScriptFetcher fetcher(&rules);
686 SynchronousSuccessDhcpFetcher dhcp_fetcher(
687 base::WideToUTF16(L"http://bingo/!FindProxyForURL"));
689 ProxyConfig config;
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) {
707 Rules rules;
708 RuleBasedProxyScriptFetcher fetcher(&rules);
709 SynchronousSuccessDhcpFetcher dhcp_fetcher(
710 base::WideToUTF16(L"http://bingo/!invalid-script"));
712 ProxyConfig config;
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> {
732 public:
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(
740 FROM_HERE,
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);
754 private:
755 GURL dummy_gurl_;
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.
764 Rules rules;
765 RuleBasedProxyScriptFetcher fetcher(&rules);
767 scoped_ptr<AsyncFailDhcpFetcher> dhcp_fetcher(new AsyncFailDhcpFetcher());
769 ProxyConfig config;
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
784 // no longer valid.
785 base::MessageLoop::current()->RunUntilIdle();
788 } // namespace
789 } // namespace net