Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / net / proxy / proxy_script_decider_unittest.cc
blob383c15975eed3da1d78a49833d884fd190fc15f8
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/net_log_unittest.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"
28 namespace net {
29 namespace {
31 enum Error {
32 kFailedDownloading = -100,
33 kFailedParsing = ERR_PAC_SCRIPT_FAILED,
36 class Rules {
37 public:
38 struct Rule {
39 Rule(const GURL& url, int fetch_error, bool is_valid_script)
40 : url(url),
41 fetch_error(fetch_error),
42 is_valid_script(is_valid_script) {
45 base::string16 text() const {
46 if (is_valid_script)
47 return base::UTF8ToUTF16(url.spec() + "!FindProxyForURL");
48 if (fetch_error == OK)
49 return base::UTF8ToUTF16(url.spec() + "!invalid-script");
50 return base::string16();
53 GURL url;
54 int fetch_error;
55 bool is_valid_script;
58 Rule AddSuccessRule(const char* url) {
59 Rule rule(GURL(url), OK /*fetch_error*/, true);
60 rules_.push_back(rule);
61 return rule;
64 void AddFailDownloadRule(const char* url) {
65 rules_.push_back(Rule(GURL(url), kFailedDownloading /*fetch_error*/,
66 false));
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();
75 ++it) {
76 if (it->url == url)
77 return *it;
79 LOG(FATAL) << "Rule not found for " << url;
80 return rules_[0];
83 const Rule& GetRuleByText(const base::string16& text) const {
84 for (RuleList::const_iterator it = rules_.begin(); it != rules_.end();
85 ++it) {
86 if (it->text() == text)
87 return *it;
89 LOG(FATAL) << "Rule not found for " << text;
90 return rules_[0];
93 private:
94 typedef std::vector<Rule> RuleList;
95 RuleList rules_;
98 class RuleBasedProxyScriptFetcher : public ProxyScriptFetcher {
99 public:
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 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);
114 if (rv == OK)
115 *text = rule.text();
116 return rv;
119 void Cancel() override {}
121 URLRequestContext* GetRequestContext() const override {
122 return request_context_;
125 private:
126 const Rules* rules_;
127 URLRequestContext* request_context_;
130 // A mock retriever, returns asynchronously when CompleteRequests() is called.
131 class MockDhcpProxyScriptFetcher : public DhcpProxyScriptFetcher {
132 public:
133 MockDhcpProxyScriptFetcher();
134 ~MockDhcpProxyScriptFetcher() override;
136 int Fetch(base::string16* utf16_text,
137 const CompletionCallback& callback) override;
138 void Cancel() override;
139 const GURL& GetPacURL() const override;
141 virtual void SetPacURL(const GURL& url);
143 virtual void CompleteRequests(int result, const base::string16& script);
145 private:
146 CompletionCallback callback_;
147 base::string16* utf16_text_;
148 GURL gurl_;
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 {
166 return gurl_;
169 void MockDhcpProxyScriptFetcher::SetPacURL(const GURL& url) {
170 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) {
181 Rules rules;
182 RuleBasedProxyScriptFetcher fetcher(&rules);
183 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
185 ProxyConfig config;
186 config.set_pac_url(GURL("http://custom/proxy.pac"));
188 Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
190 TestCompletionCallback callback;
191 TestNetLog log;
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 TestNetLog::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) {
217 Rules rules;
218 RuleBasedProxyScriptFetcher fetcher(&rules);
219 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
221 ProxyConfig config;
222 config.set_pac_url(GURL("http://custom/proxy.pac"));
224 rules.AddFailDownloadRule("http://custom/proxy.pac");
226 TestCompletionCallback callback;
227 TestNetLog log;
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 TestNetLog::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) {
253 Rules rules;
254 RuleBasedProxyScriptFetcher fetcher(&rules);
255 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
257 ProxyConfig config;
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) {
272 Rules rules;
273 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
275 ProxyConfig config;
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) {
288 Rules rules;
289 RuleBasedProxyScriptFetcher fetcher(&rules);
290 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
292 ProxyConfig config;
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 {
308 public:
309 ProxyScriptDeciderQuickCheckTest()
310 : rule_(rules_.AddSuccessRule("http://wpad/wpad.dat")),
311 fetcher_(&rules_) { }
313 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));
320 int StartDecider() {
321 return decider_->Start(config_, base::TimeDelta(), true,
322 callback_.callback());
325 protected:
326 scoped_ptr<ProxyScriptDecider> decider_;
327 MockHostResolver resolver_;
328 Rules rules_;
329 Rules::Rule rule_;
330 TestCompletionCallback callback_;
331 RuleBasedProxyScriptFetcher fetcher_;
332 ProxyConfig config_;
333 DoNothingDhcpProxyScriptFetcher dhcp_fetcher_;
335 private:
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
352 // fail.
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
407 // asked to fetch.
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 // Regression test for http://crbug.com/409698.
432 // This test lets the state machine get into state QUICK_CHECK_COMPLETE, then
433 // destroys the decider, causing a cancel.
434 TEST_F(ProxyScriptDeciderQuickCheckTest, CancelPartway) {
435 resolver_.set_synchronous_mode(false);
436 resolver_.set_ondemand_mode(true);
437 EXPECT_EQ(ERR_IO_PENDING, StartDecider());
438 decider_.reset(NULL);
441 // Fails at WPAD (downloading), but succeeds in choosing the custom PAC.
442 TEST(ProxyScriptDeciderTest, AutodetectFailCustomSuccess1) {
443 Rules rules;
444 RuleBasedProxyScriptFetcher fetcher(&rules);
445 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
447 ProxyConfig config;
448 config.set_auto_detect(true);
449 config.set_pac_url(GURL("http://custom/proxy.pac"));
451 rules.AddFailDownloadRule("http://wpad/wpad.dat");
452 Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
454 TestCompletionCallback callback;
455 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
456 EXPECT_EQ(OK, decider.Start(
457 config, base::TimeDelta(), true, callback.callback()));
458 EXPECT_EQ(rule.text(), decider.script_data()->utf16());
460 EXPECT_TRUE(decider.effective_config().has_pac_url());
461 EXPECT_EQ(rule.url, decider.effective_config().pac_url());
464 // Fails at WPAD (no DHCP config, DNS PAC fails parsing), but succeeds in
465 // choosing the custom PAC.
466 TEST(ProxyScriptDeciderTest, AutodetectFailCustomSuccess2) {
467 Rules rules;
468 RuleBasedProxyScriptFetcher fetcher(&rules);
469 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
471 ProxyConfig config;
472 config.set_auto_detect(true);
473 config.set_pac_url(GURL("http://custom/proxy.pac"));
474 config.proxy_rules().ParseFromString("unused-manual-proxy:99");
476 rules.AddFailParsingRule("http://wpad/wpad.dat");
477 Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");
479 TestCompletionCallback callback;
480 TestNetLog log;
482 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
483 EXPECT_EQ(OK, decider.Start(config, base::TimeDelta(),
484 true, callback.callback()));
485 EXPECT_EQ(rule.text(), decider.script_data()->utf16());
487 // Verify that the effective configuration no longer contains auto detect or
488 // any of the manual settings.
489 EXPECT_TRUE(decider.effective_config().Equals(
490 ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac"))));
492 // Check the NetLog was filled correctly.
493 // (Note that various states are repeated since both WPAD and custom
494 // PAC scripts are tried).
495 TestNetLog::CapturedEntryList entries;
496 log.GetEntries(&entries);
498 EXPECT_EQ(10u, entries.size());
499 EXPECT_TRUE(LogContainsBeginEvent(
500 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
501 // This is the DHCP phase, which fails fetching rather than parsing, so
502 // there is no pair of SET_PAC_SCRIPT events.
503 EXPECT_TRUE(LogContainsBeginEvent(
504 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
505 EXPECT_TRUE(LogContainsEndEvent(
506 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
507 EXPECT_TRUE(LogContainsEvent(
508 entries, 3,
509 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
510 NetLog::PHASE_NONE));
511 // This is the DNS phase, which attempts a fetch but fails.
512 EXPECT_TRUE(LogContainsBeginEvent(
513 entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
514 EXPECT_TRUE(LogContainsEndEvent(
515 entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
516 EXPECT_TRUE(LogContainsEvent(
517 entries, 6,
518 NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
519 NetLog::PHASE_NONE));
520 // Finally, the custom PAC URL phase.
521 EXPECT_TRUE(LogContainsBeginEvent(
522 entries, 7, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
523 EXPECT_TRUE(LogContainsEndEvent(
524 entries, 8, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
525 EXPECT_TRUE(LogContainsEndEvent(
526 entries, 9, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
529 // Fails at WPAD (downloading), and fails at custom PAC (downloading).
530 TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails1) {
531 Rules rules;
532 RuleBasedProxyScriptFetcher fetcher(&rules);
533 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
535 ProxyConfig config;
536 config.set_auto_detect(true);
537 config.set_pac_url(GURL("http://custom/proxy.pac"));
539 rules.AddFailDownloadRule("http://wpad/wpad.dat");
540 rules.AddFailDownloadRule("http://custom/proxy.pac");
542 TestCompletionCallback callback;
543 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
544 EXPECT_EQ(kFailedDownloading,
545 decider.Start(config, base::TimeDelta(), true,
546 callback.callback()));
547 EXPECT_EQ(NULL, decider.script_data());
550 // Fails at WPAD (downloading), and fails at custom PAC (parsing).
551 TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails2) {
552 Rules rules;
553 RuleBasedProxyScriptFetcher fetcher(&rules);
554 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
556 ProxyConfig config;
557 config.set_auto_detect(true);
558 config.set_pac_url(GURL("http://custom/proxy.pac"));
560 rules.AddFailDownloadRule("http://wpad/wpad.dat");
561 rules.AddFailParsingRule("http://custom/proxy.pac");
563 TestCompletionCallback callback;
564 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
565 EXPECT_EQ(kFailedParsing,
566 decider.Start(config, base::TimeDelta(), true,
567 callback.callback()));
568 EXPECT_EQ(NULL, decider.script_data());
571 // This is a copy-paste of CustomPacFails1, with the exception that we give it
572 // a 1 millisecond delay. This means it will now complete asynchronously.
573 // Moreover, we test the NetLog to make sure it logged the pause.
574 TEST(ProxyScriptDeciderTest, CustomPacFails1_WithPositiveDelay) {
575 Rules rules;
576 RuleBasedProxyScriptFetcher fetcher(&rules);
577 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
579 ProxyConfig config;
580 config.set_pac_url(GURL("http://custom/proxy.pac"));
582 rules.AddFailDownloadRule("http://custom/proxy.pac");
584 TestCompletionCallback callback;
585 TestNetLog log;
586 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
587 EXPECT_EQ(ERR_IO_PENDING,
588 decider.Start(config, base::TimeDelta::FromMilliseconds(1),
589 true, callback.callback()));
591 EXPECT_EQ(kFailedDownloading, callback.WaitForResult());
592 EXPECT_EQ(NULL, decider.script_data());
594 // Check the NetLog was filled correctly.
595 TestNetLog::CapturedEntryList entries;
596 log.GetEntries(&entries);
598 EXPECT_EQ(6u, entries.size());
599 EXPECT_TRUE(LogContainsBeginEvent(
600 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
601 EXPECT_TRUE(LogContainsBeginEvent(
602 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT));
603 EXPECT_TRUE(LogContainsEndEvent(
604 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT));
605 EXPECT_TRUE(LogContainsBeginEvent(
606 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
607 EXPECT_TRUE(LogContainsEndEvent(
608 entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
609 EXPECT_TRUE(LogContainsEndEvent(
610 entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
613 // This is a copy-paste of CustomPacFails1, with the exception that we give it
614 // a -5 second delay instead of a 0 ms delay. This change should have no effect
615 // so the rest of the test is unchanged.
616 TEST(ProxyScriptDeciderTest, CustomPacFails1_WithNegativeDelay) {
617 Rules rules;
618 RuleBasedProxyScriptFetcher fetcher(&rules);
619 DoNothingDhcpProxyScriptFetcher dhcp_fetcher;
621 ProxyConfig config;
622 config.set_pac_url(GURL("http://custom/proxy.pac"));
624 rules.AddFailDownloadRule("http://custom/proxy.pac");
626 TestCompletionCallback callback;
627 TestNetLog log;
628 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log);
629 EXPECT_EQ(kFailedDownloading,
630 decider.Start(config, base::TimeDelta::FromSeconds(-5),
631 true, callback.callback()));
632 EXPECT_EQ(NULL, decider.script_data());
634 // Check the NetLog was filled correctly.
635 TestNetLog::CapturedEntryList entries;
636 log.GetEntries(&entries);
638 EXPECT_EQ(4u, entries.size());
639 EXPECT_TRUE(LogContainsBeginEvent(
640 entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
641 EXPECT_TRUE(LogContainsBeginEvent(
642 entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
643 EXPECT_TRUE(LogContainsEndEvent(
644 entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT));
645 EXPECT_TRUE(LogContainsEndEvent(
646 entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER));
649 class SynchronousSuccessDhcpFetcher : public DhcpProxyScriptFetcher {
650 public:
651 explicit SynchronousSuccessDhcpFetcher(const base::string16& expected_text)
652 : gurl_("http://dhcppac/"), expected_text_(expected_text) {
655 int Fetch(base::string16* utf16_text,
656 const CompletionCallback& callback) override {
657 *utf16_text = expected_text_;
658 return OK;
661 void Cancel() override {}
663 const GURL& GetPacURL() const override { return gurl_; }
665 const base::string16& expected_text() const {
666 return expected_text_;
669 private:
670 GURL gurl_;
671 base::string16 expected_text_;
673 DISALLOW_COPY_AND_ASSIGN(SynchronousSuccessDhcpFetcher);
676 // All of the tests above that use ProxyScriptDecider have tested
677 // failure to fetch a PAC file via DHCP configuration, so we now test
678 // success at downloading and parsing, and then success at downloading,
679 // failure at parsing.
681 TEST(ProxyScriptDeciderTest, AutodetectDhcpSuccess) {
682 Rules rules;
683 RuleBasedProxyScriptFetcher fetcher(&rules);
684 SynchronousSuccessDhcpFetcher dhcp_fetcher(
685 base::WideToUTF16(L"http://bingo/!FindProxyForURL"));
687 ProxyConfig config;
688 config.set_auto_detect(true);
690 rules.AddSuccessRule("http://bingo/");
691 rules.AddFailDownloadRule("http://wpad/wpad.dat");
693 TestCompletionCallback callback;
694 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
695 EXPECT_EQ(OK, decider.Start(
696 config, base::TimeDelta(), true, callback.callback()));
697 EXPECT_EQ(dhcp_fetcher.expected_text(),
698 decider.script_data()->utf16());
700 EXPECT_TRUE(decider.effective_config().has_pac_url());
701 EXPECT_EQ(GURL("http://dhcppac/"), decider.effective_config().pac_url());
704 TEST(ProxyScriptDeciderTest, AutodetectDhcpFailParse) {
705 Rules rules;
706 RuleBasedProxyScriptFetcher fetcher(&rules);
707 SynchronousSuccessDhcpFetcher dhcp_fetcher(
708 base::WideToUTF16(L"http://bingo/!invalid-script"));
710 ProxyConfig config;
711 config.set_auto_detect(true);
713 rules.AddFailParsingRule("http://bingo/");
714 rules.AddFailDownloadRule("http://wpad/wpad.dat");
716 TestCompletionCallback callback;
717 ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL);
718 // Since there is fallback to DNS-based WPAD, the final error will be that
719 // it failed downloading, not that it failed parsing.
720 EXPECT_EQ(kFailedDownloading,
721 decider.Start(config, base::TimeDelta(), true, callback.callback()));
722 EXPECT_EQ(NULL, decider.script_data());
724 EXPECT_FALSE(decider.effective_config().has_pac_url());
727 class AsyncFailDhcpFetcher
728 : public DhcpProxyScriptFetcher,
729 public base::SupportsWeakPtr<AsyncFailDhcpFetcher> {
730 public:
731 AsyncFailDhcpFetcher() {}
732 ~AsyncFailDhcpFetcher() override {}
734 int Fetch(base::string16* utf16_text,
735 const CompletionCallback& callback) override {
736 callback_ = callback;
737 base::MessageLoop::current()->PostTask(
738 FROM_HERE,
739 base::Bind(&AsyncFailDhcpFetcher::CallbackWithFailure, AsWeakPtr()));
740 return ERR_IO_PENDING;
743 void Cancel() override { callback_.Reset(); }
745 const GURL& GetPacURL() const override { return dummy_gurl_; }
747 void CallbackWithFailure() {
748 if (!callback_.is_null())
749 callback_.Run(ERR_PAC_NOT_IN_DHCP);
752 private:
753 GURL dummy_gurl_;
754 CompletionCallback callback_;
757 TEST(ProxyScriptDeciderTest, DhcpCancelledByDestructor) {
758 // This regression test would crash before
759 // http://codereview.chromium.org/7044058/
760 // Thus, we don't care much about actual results (hence no EXPECT or ASSERT
761 // macros below), just that it doesn't crash.
762 Rules rules;
763 RuleBasedProxyScriptFetcher fetcher(&rules);
765 scoped_ptr<AsyncFailDhcpFetcher> dhcp_fetcher(new AsyncFailDhcpFetcher());
767 ProxyConfig config;
768 config.set_auto_detect(true);
769 rules.AddFailDownloadRule("http://wpad/wpad.dat");
771 TestCompletionCallback callback;
773 // Scope so ProxyScriptDecider gets destroyed early.
775 ProxyScriptDecider decider(&fetcher, dhcp_fetcher.get(), NULL);
776 decider.Start(config, base::TimeDelta(), true, callback.callback());
779 // Run the message loop to let the DHCP fetch complete and post the results
780 // back. Before the fix linked to above, this would try to invoke on
781 // the callback object provided by ProxyScriptDecider after it was
782 // no longer valid.
783 base::MessageLoop::current()->RunUntilIdle();
786 } // namespace
787 } // namespace net