diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-13 22:06:36 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-13 22:06:36 +0000 |
commit | 778ad81ac45f75d4904aa18f079a07b88aefbe7c (patch) | |
tree | 82625e77f1e7180093fe6bc6f1e96f2e86412af7 /net/proxy/proxy_script_decider_unittest.cc | |
parent | 3ed14d115e905131fc729b5661b203facdd90233 (diff) | |
download | chromium_src-778ad81ac45f75d4904aa18f079a07b88aefbe7c.zip chromium_src-778ad81ac45f75d4904aa18f079a07b88aefbe7c.tar.gz chromium_src-778ad81ac45f75d4904aa18f079a07b88aefbe7c.tar.bz2 |
Refactor: Extract "InitProxyResolver" to "ProxyScriptDecider".
This is primarily a rename, with the exception that the initialization of ProxyResolver (i.e. the javascript runtime environment for the PAC script) is no longer done inside of ProxyScriptDecider.
The motivation for doing this is to make it possible to poll our automatic proxy settings (PAC URLs or WPAD) in the background, _without_ needing to feed the scripts into the javascript parser for validation.
There likely won't be any user-visible consequence of this change, however the new mechanism is weaker than the original -- it is possible for the PAC selection to now choose a PAC script which fails to parse as javascript, even though there was a later fallback choice which does parse. This should be rare though (the bad response would need to contain the substring "FindProxyForURL").
BUG=TODO (bugtracker down right now)
Review URL: http://codereview.chromium.org/8896019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114281 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/proxy/proxy_script_decider_unittest.cc')
-rw-r--r-- | net/proxy/proxy_script_decider_unittest.cc | 590 |
1 files changed, 590 insertions, 0 deletions
diff --git a/net/proxy/proxy_script_decider_unittest.cc b/net/proxy/proxy_script_decider_unittest.cc new file mode 100644 index 0000000..f2d6c82 --- /dev/null +++ b/net/proxy/proxy_script_decider_unittest.cc @@ -0,0 +1,590 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> + +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/base/net_log_unittest.h" +#include "net/base/test_completion_callback.h" +#include "net/proxy/dhcp_proxy_script_fetcher.h" +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_resolver.h" +#include "net/proxy/proxy_script_decider.h" +#include "net/proxy/proxy_script_fetcher.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace { + +enum Error { + kFailedDownloading = -100, + kFailedParsing = ERR_PAC_SCRIPT_FAILED, +}; + +class Rules { + public: + struct Rule { + Rule(const GURL& url, int fetch_error, bool is_valid_script) + : url(url), + fetch_error(fetch_error), + is_valid_script(is_valid_script) { + } + + string16 text() const { + if (is_valid_script) + return UTF8ToUTF16(url.spec() + "!FindProxyForURL"); + if (fetch_error == OK) + return UTF8ToUTF16(url.spec() + "!invalid-script"); + return string16(); + } + + GURL url; + int fetch_error; + bool is_valid_script; + }; + + Rule AddSuccessRule(const char* url) { + Rule rule(GURL(url), OK /*fetch_error*/, true); + rules_.push_back(rule); + return rule; + } + + void AddFailDownloadRule(const char* url) { + rules_.push_back(Rule(GURL(url), kFailedDownloading /*fetch_error*/, + false)); + } + + void AddFailParsingRule(const char* url) { + rules_.push_back(Rule(GURL(url), OK /*fetch_error*/, false)); + } + + const Rule& GetRuleByUrl(const GURL& url) const { + for (RuleList::const_iterator it = rules_.begin(); it != rules_.end(); + ++it) { + if (it->url == url) + return *it; + } + LOG(FATAL) << "Rule not found for " << url; + return rules_[0]; + } + + const Rule& GetRuleByText(const string16& text) const { + for (RuleList::const_iterator it = rules_.begin(); it != rules_.end(); + ++it) { + if (it->text() == text) + return *it; + } + LOG(FATAL) << "Rule not found for " << text; + return rules_[0]; + } + + private: + typedef std::vector<Rule> RuleList; + RuleList rules_; +}; + +class RuleBasedProxyScriptFetcher : public ProxyScriptFetcher { + public: + explicit RuleBasedProxyScriptFetcher(const Rules* rules) : rules_(rules) {} + + // ProxyScriptFetcher implementation. + virtual int Fetch(const GURL& url, + string16* text, + OldCompletionCallback* callback) { + const Rules::Rule& rule = rules_->GetRuleByUrl(url); + int rv = rule.fetch_error; + EXPECT_NE(ERR_UNEXPECTED, rv); + if (rv == OK) + *text = rule.text(); + return rv; + } + + virtual void Cancel() {} + + virtual URLRequestContext* GetRequestContext() const { return NULL; } + + private: + const Rules* rules_; +}; + +// Succeed using custom PAC script. +TEST(ProxyScriptDeciderTest, CustomPacSucceeds) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_pac_url(GURL("http://custom/proxy.pac")); + + Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + CapturingNetLog log(CapturingNetLog::kUnbounded); + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); + EXPECT_EQ(OK, decider.Start( + config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + + // Check the NetLog was filled correctly. + CapturingNetLog::EntryList entries; + log.GetEntries(&entries); + + EXPECT_EQ(4u, entries.size()); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); + + EXPECT_TRUE(decider.effective_config().has_pac_url()); + EXPECT_EQ(config.pac_url(), decider.effective_config().pac_url()); +} + +// Fail downloading the custom PAC script. +TEST(ProxyScriptDeciderTest, CustomPacFails1) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_pac_url(GURL("http://custom/proxy.pac")); + + rules.AddFailDownloadRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + CapturingNetLog log(CapturingNetLog::kUnbounded); + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); + EXPECT_EQ(kFailedDownloading, + decider.Start(config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(NULL, decider.script_data()); + + // Check the NetLog was filled correctly. + CapturingNetLog::EntryList entries; + log.GetEntries(&entries); + + EXPECT_EQ(4u, entries.size()); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); + + EXPECT_FALSE(decider.effective_config().has_pac_url()); +} + +// Fail parsing the custom PAC script. +TEST(ProxyScriptDeciderTest, CustomPacFails2) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_pac_url(GURL("http://custom/proxy.pac")); + + rules.AddFailParsingRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL); + EXPECT_EQ(kFailedParsing, + decider.Start(config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(NULL, decider.script_data()); +} + +// Fail downloading the custom PAC script, because the fetcher was NULL. +TEST(ProxyScriptDeciderTest, HasNullProxyScriptFetcher) { + Rules rules; + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_pac_url(GURL("http://custom/proxy.pac")); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(NULL, &dhcp_fetcher, NULL); + EXPECT_EQ(ERR_UNEXPECTED, + decider.Start(config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(NULL, decider.script_data()); +} + +// Succeeds in choosing autodetect (WPAD DNS). +TEST(ProxyScriptDeciderTest, AutodetectSuccess) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_auto_detect(true); + + Rules::Rule rule = rules.AddSuccessRule("http://wpad/wpad.dat"); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL); + EXPECT_EQ(OK, decider.Start( + config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + + EXPECT_TRUE(decider.effective_config().has_pac_url()); + EXPECT_EQ(rule.url, decider.effective_config().pac_url()); +} + +// Fails at WPAD (downloading), but succeeds in choosing the custom PAC. +TEST(ProxyScriptDeciderTest, AutodetectFailCustomSuccess1) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_auto_detect(true); + config.set_pac_url(GURL("http://custom/proxy.pac")); + + rules.AddFailDownloadRule("http://wpad/wpad.dat"); + Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL); + EXPECT_EQ(OK, decider.Start( + config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + + EXPECT_TRUE(decider.effective_config().has_pac_url()); + EXPECT_EQ(rule.url, decider.effective_config().pac_url()); +} + +// Fails at WPAD (no DHCP config, DNS PAC fails parsing), but succeeds in +// choosing the custom PAC. +TEST(ProxyScriptDeciderTest, AutodetectFailCustomSuccess2) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_auto_detect(true); + config.set_pac_url(GURL("http://custom/proxy.pac")); + config.proxy_rules().ParseFromString("unused-manual-proxy:99"); + + rules.AddFailParsingRule("http://wpad/wpad.dat"); + Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + CapturingNetLog log(CapturingNetLog::kUnbounded); + + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); + EXPECT_EQ(OK, decider.Start(config, base::TimeDelta(), + true, &callback)); + EXPECT_EQ(rule.text(), decider.script_data()->utf16()); + + // Verify that the effective configuration no longer contains auto detect or + // any of the manual settings. + EXPECT_TRUE(decider.effective_config().Equals( + ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac")))); + + // Check the NetLog was filled correctly. + // (Note that various states are repeated since both WPAD and custom + // PAC scripts are tried). + CapturingNetLog::EntryList entries; + log.GetEntries(&entries); + + EXPECT_EQ(10u, entries.size()); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); + // This is the DHCP phase, which fails fetching rather than parsing, so + // there is no pair of SET_PAC_SCRIPT events. + EXPECT_TRUE(LogContainsBeginEvent( + entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEvent( + entries, 3, + NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE, + NetLog::PHASE_NONE)); + // This is the DNS phase, which attempts a fetch but fails. + EXPECT_TRUE(LogContainsBeginEvent( + entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEvent( + entries, 6, + NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE, + NetLog::PHASE_NONE)); + // Finally, the custom PAC URL phase. + EXPECT_TRUE(LogContainsBeginEvent( + entries, 7, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 8, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 9, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); +} + +// Fails at WPAD (downloading), and fails at custom PAC (downloading). +TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails1) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_auto_detect(true); + config.set_pac_url(GURL("http://custom/proxy.pac")); + + rules.AddFailDownloadRule("http://wpad/wpad.dat"); + rules.AddFailDownloadRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL); + EXPECT_EQ(kFailedDownloading, + decider.Start(config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(NULL, decider.script_data()); +} + +// Fails at WPAD (downloading), and fails at custom PAC (parsing). +TEST(ProxyScriptDeciderTest, AutodetectFailCustomFails2) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_auto_detect(true); + config.set_pac_url(GURL("http://custom/proxy.pac")); + + rules.AddFailDownloadRule("http://wpad/wpad.dat"); + rules.AddFailParsingRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL); + EXPECT_EQ(kFailedParsing, + decider.Start(config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(NULL, decider.script_data()); +} + +// This is a copy-paste of CustomPacFails1, with the exception that we give it +// a 1 millisecond delay. This means it will now complete asynchronously. +// Moreover, we test the NetLog to make sure it logged the pause. +TEST(ProxyScriptDeciderTest, CustomPacFails1_WithPositiveDelay) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_pac_url(GURL("http://custom/proxy.pac")); + + rules.AddFailDownloadRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + CapturingNetLog log(CapturingNetLog::kUnbounded); + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); + EXPECT_EQ(ERR_IO_PENDING, + decider.Start(config, base::TimeDelta::FromMilliseconds(1), + true, &callback)); + + EXPECT_EQ(kFailedDownloading, callback.WaitForResult()); + EXPECT_EQ(NULL, decider.script_data()); + + // Check the NetLog was filled correctly. + CapturingNetLog::EntryList entries; + log.GetEntries(&entries); + + EXPECT_EQ(6u, entries.size()); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT)); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 4, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 5, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); +} + +// This is a copy-paste of CustomPacFails1, with the exception that we give it +// a -5 second delay instead of a 0 ms delay. This change should have no effect +// so the rest of the test is unchanged. +TEST(ProxyScriptDeciderTest, CustomPacFails1_WithNegativeDelay) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + DoNothingDhcpProxyScriptFetcher dhcp_fetcher; + + ProxyConfig config; + config.set_pac_url(GURL("http://custom/proxy.pac")); + + rules.AddFailDownloadRule("http://custom/proxy.pac"); + + TestOldCompletionCallback callback; + CapturingNetLog log(CapturingNetLog::kUnbounded); + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, &log); + EXPECT_EQ(kFailedDownloading, + decider.Start(config, base::TimeDelta::FromSeconds(-5), + true, &callback)); + EXPECT_EQ(NULL, decider.script_data()); + + // Check the NetLog was filled correctly. + CapturingNetLog::EntryList entries; + log.GetEntries(&entries); + + EXPECT_EQ(4u, entries.size()); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 0, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); + EXPECT_TRUE(LogContainsBeginEvent( + entries, 1, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 2, NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT)); + EXPECT_TRUE(LogContainsEndEvent( + entries, 3, NetLog::TYPE_PROXY_SCRIPT_DECIDER)); +} + +class SynchronousSuccessDhcpFetcher : public DhcpProxyScriptFetcher { + public: + explicit SynchronousSuccessDhcpFetcher(const string16& expected_text) + : gurl_("http://dhcppac/"), expected_text_(expected_text) { + } + + int Fetch(string16* utf16_text, OldCompletionCallback* callback) OVERRIDE { + *utf16_text = expected_text_; + return OK; + } + + void Cancel() OVERRIDE { + } + + const GURL& GetPacURL() const OVERRIDE { + return gurl_; + } + + const string16& expected_text() const { + return expected_text_; + } + + private: + GURL gurl_; + string16 expected_text_; + + DISALLOW_COPY_AND_ASSIGN(SynchronousSuccessDhcpFetcher); +}; + +// All of the tests above that use ProxyScriptDecider have tested +// failure to fetch a PAC file via DHCP configuration, so we now test +// success at downloading and parsing, and then success at downloading, +// failure at parsing. + +TEST(ProxyScriptDeciderTest, AutodetectDhcpSuccess) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + SynchronousSuccessDhcpFetcher dhcp_fetcher( + WideToUTF16(L"http://bingo/!FindProxyForURL")); + + ProxyConfig config; + config.set_auto_detect(true); + + rules.AddSuccessRule("http://bingo/"); + rules.AddFailDownloadRule("http://wpad/wpad.dat"); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL); + EXPECT_EQ(OK, decider.Start( + config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(dhcp_fetcher.expected_text(), + decider.script_data()->utf16()); + + EXPECT_TRUE(decider.effective_config().has_pac_url()); + EXPECT_EQ(GURL("http://dhcppac/"), decider.effective_config().pac_url()); +} + +TEST(ProxyScriptDeciderTest, AutodetectDhcpFailParse) { + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + SynchronousSuccessDhcpFetcher dhcp_fetcher( + WideToUTF16(L"http://bingo/!invalid-script")); + + ProxyConfig config; + config.set_auto_detect(true); + + rules.AddFailParsingRule("http://bingo/"); + rules.AddFailDownloadRule("http://wpad/wpad.dat"); + + TestOldCompletionCallback callback; + ProxyScriptDecider decider(&fetcher, &dhcp_fetcher, NULL); + // Since there is fallback to DNS-based WPAD, the final error will be that + // it failed downloading, not that it failed parsing. + EXPECT_EQ(kFailedDownloading, + decider.Start(config, base::TimeDelta(), true, &callback)); + EXPECT_EQ(NULL, decider.script_data()); + + EXPECT_FALSE(decider.effective_config().has_pac_url()); +} + +class AsyncFailDhcpFetcher + : public DhcpProxyScriptFetcher, + public base::RefCountedThreadSafe<AsyncFailDhcpFetcher> { + public: + AsyncFailDhcpFetcher() : callback_(NULL) { + } + + int Fetch(string16* utf16_text, OldCompletionCallback* callback) OVERRIDE { + callback_ = callback; + MessageLoop::current()->PostTask( + FROM_HERE, + NewRunnableMethod(this, &AsyncFailDhcpFetcher::CallbackWithFailure)); + return ERR_IO_PENDING; + } + + void Cancel() OVERRIDE { + callback_ = NULL; + } + + const GURL& GetPacURL() const OVERRIDE { + return dummy_gurl_; + } + + void CallbackWithFailure() { + if (callback_) + callback_->Run(ERR_PAC_NOT_IN_DHCP); + } + + private: + GURL dummy_gurl_; + OldCompletionCallback* callback_; +}; + +TEST(ProxyScriptDeciderTest, DhcpCancelledByDestructor) { + // This regression test would crash before + // http://codereview.chromium.org/7044058/ + // Thus, we don't care much about actual results (hence no EXPECT or ASSERT + // macros below), just that it doesn't crash. + Rules rules; + RuleBasedProxyScriptFetcher fetcher(&rules); + + scoped_refptr<AsyncFailDhcpFetcher> dhcp_fetcher(new AsyncFailDhcpFetcher()); + + ProxyConfig config; + config.set_auto_detect(true); + rules.AddFailDownloadRule("http://wpad/wpad.dat"); + + TestOldCompletionCallback callback; + + // Scope so ProxyScriptDecider gets destroyed early. + { + ProxyScriptDecider decider(&fetcher, dhcp_fetcher.get(), NULL); + decider.Start(config, base::TimeDelta(), true, &callback); + } + + // Run the message loop to let the DHCP fetch complete and post the results + // back. Before the fix linked to above, this would try to invoke on + // the callback object provided by ProxyScriptDecider after it was + // no longer valid. + MessageLoop::current()->RunAllPending(); +} + +} // namespace +} // namespace net |