Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1454)

Unified Diff: chrome/browser/net/predictor_browsertest.cc

Issue 1989363007: Move predictor dns unit tests to browser tests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Hopefully fixed 469120 Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/net/predictor_browsertest.cc
diff --git a/chrome/browser/net/predictor_browsertest.cc b/chrome/browser/net/predictor_browsertest.cc
index be8568ae32814a97956936b9c6ac16cc3cb4b7b7..712d5b418faa18f446b1eb6ef78ba7cc3a1e0674 100644
--- a/chrome/browser/net/predictor_browsertest.cc
+++ b/chrome/browser/net/predictor_browsertest.cc
@@ -249,56 +249,79 @@ class ConnectionListener
// and immediately fails the resolution requests themselves.
class HostResolutionRequestRecorder : public net::HostResolverProc {
public:
- HostResolutionRequestRecorder()
- : HostResolverProc(NULL),
- is_waiting_for_hostname_(false) {
- }
+ explicit HostResolutionRequestRecorder(net::HostResolverProc* previous)
+ : HostResolverProc(previous), run_loop_(nullptr) {}
int Resolve(const std::string& host,
net::AddressFamily address_family,
net::HostResolverFlags host_resolver_flags,
net::AddressList* addrlist,
int* os_error) override {
+ // Note the rule based proc sleep synchronously.
Randy Smith (Not in Mondays) 2016/05/23 19:55:18 Sorry, I'm getting past the lexing phase, but fail
Charlie Harrison 2016/05/24 16:57:06 Hahaha yeah that's extremely confusing. I meant th
+ int result = ResolveUsingPrevious(host, address_family, host_resolver_flags,
+ addrlist, os_error);
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
+ BrowserThread::IO, FROM_HERE,
base::Bind(&HostResolutionRequestRecorder::AddToHistory,
- base::Unretained(this),
- host));
- return net::ERR_NAME_NOT_RESOLVED;
+ base::Unretained(this), host));
+ return result;
}
int RequestedHostnameCount() const {
+ base::AutoLock lock(lock_);
return requested_hostnames_.size();
}
bool HasHostBeenRequested(const std::string& hostname) const {
+ base::AutoLock lock(lock_);
+ return HasHostBeenRequestedLocked(hostname);
+ }
+
+ bool HasHostBeenRequestedLocked(const std::string& hostname) const {
+ lock_.AssertAcquired();
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return std::find(requested_hostnames_.begin(),
requested_hostnames_.end(),
hostname) != requested_hostnames_.end();
}
+ void WaitUntilHostNamesHaveBeenRequested(
+ const network_hints::UrlList& names) {
+ for (const auto& name : names) {
+ WaitUntilHostHasBeenRequested(name.host());
+ }
+ }
+
void WaitUntilHostHasBeenRequested(const std::string& hostname) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_waiting_for_hostname_);
- if (HasHostBeenRequested(hostname))
- return;
- waiting_for_hostname_ = hostname;
- is_waiting_for_hostname_ = true;
- content::RunMessageLoop();
+ base::RunLoop run_loop;
+ {
+ base::AutoLock lock(lock_);
+ if (HasHostBeenRequestedLocked(hostname))
+ return;
+ waiting_for_hostname_ = hostname;
+ DCHECK(!run_loop_);
+ run_loop_ = &run_loop;
+ }
+ run_loop_->Run();
+ }
+
+ void set_task_runner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ task_runner_.swap(task_runner);
}
private:
~HostResolutionRequestRecorder() override {}
void AddToHistory(const std::string& hostname) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ base::AutoLock lock(lock_);
requested_hostnames_.push_back(hostname);
- if (is_waiting_for_hostname_ && waiting_for_hostname_ == hostname) {
- is_waiting_for_hostname_ = false;
+ if (run_loop_ && waiting_for_hostname_ == hostname) {
waiting_for_hostname_.clear();
- base::MessageLoop::current()->QuitWhenIdle();
+ task_runner_->PostTask(FROM_HERE, run_loop_->QuitClosure());
+ run_loop_ = nullptr;
}
}
@@ -306,14 +329,17 @@ class HostResolutionRequestRecorder : public net::HostResolverProc {
// to be requested.
std::string waiting_for_hostname_;
- // Whether WaitUntilHostHasBeenRequested is waiting for a hostname to be
- // requested and thus is running a nested message loop.
- bool is_waiting_for_hostname_;
-
// A list of hostnames for which resolution has already been requested. Only
// to be accessed from the UI thread.
std::vector<std::string> requested_hostnames_;
+ base::RunLoop* run_loop_;
+
+ // Protects |waiting_for_hostname_| and |requested_hostnames_|.
+ mutable base::Lock lock_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder);
};
@@ -449,8 +475,21 @@ class PredictorBrowserTest : public InProcessBrowserTest {
: startup_url_("http://host1:1"),
referring_url_("http://host2:1"),
target_url_("http://host3:1"),
- host_resolution_request_recorder_(new HostResolutionRequestRecorder),
- cross_site_test_server_(new net::EmbeddedTestServer()) {}
+ rule_based_resolver_proc_(new net::RuleBasedHostResolverProc(nullptr)),
+ host_resolution_request_recorder_(
+ new HostResolutionRequestRecorder(rule_based_resolver_proc_.get())),
+ cross_site_test_server_(new net::EmbeddedTestServer()) {
+ rule_based_resolver_proc_->AddRuleWithLatency("www.example.test",
+ "127.0.0.1", 50);
+ rule_based_resolver_proc_->AddRuleWithLatency("gmail.google.com",
+ "127.0.0.1", 70);
+ rule_based_resolver_proc_->AddRuleWithLatency("mail.google.com",
+ "127.0.0.1", 44);
+ rule_based_resolver_proc_->AddRuleWithLatency("gmail.com", "127.0.0.1", 63);
+ rule_based_resolver_proc_->AddSimulatedFailure("*.notfound");
+ rule_based_resolver_proc_->AddRuleWithLatency("delay.google.com",
+ "127.0.0.1", 1000 * 60);
+ }
protected:
void SetUpInProcessBrowserTestFixture() override {
@@ -466,11 +505,14 @@ class PredictorBrowserTest : public InProcessBrowserTest {
switches::kEnableBlinkFeatures, kBlinkPreconnectFeature);
command_line->AppendSwitchASCII(switches::kEnableFeatures,
"PreconnectMore");
+ command_line->AppendSwitchASCII(switches::kEnableFeatures,
+ "UsePredictorDNSQueue");
}
void SetUpOnMainThread() override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
task_runner_ = base::ThreadTaskRunnerHandle::Get();
+ host_resolution_request_recorder_->set_task_runner(task_runner_);
cross_site_test_server_->ServeFilesFromSourceDirectory("chrome/test/data/");
connection_listener_.reset(new ConnectionListener());
@@ -581,10 +623,31 @@ class PredictorBrowserTest : public InProcessBrowserTest {
host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname);
}
+ void WaitUntilHostNamesHaveBeenRequested(
+ const network_hints::UrlList& names) {
+ host_resolution_request_recorder_->WaitUntilHostNamesHaveBeenRequested(
+ names);
+ }
+
int RequestedHostnameCount() const {
return host_resolution_request_recorder_->RequestedHostnameCount();
}
+ void FloodResolveRequestsOnUIThread(const network_hints::UrlList& names) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PredictorBrowserTest::FloodResolveRequests, this, names));
+ }
+
+ void FloodResolveRequests(const network_hints::UrlList& names) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (int i = 0; i < 10; i++) {
+ predictor()->DnsPrefetchMotivatedList(names,
+ UrlInfo::PAGE_SCAN_MOTIVATED);
+ }
+ }
+
net::EmbeddedTestServer* cross_site_test_server() {
return cross_site_test_server_.get();
}
@@ -639,6 +702,31 @@ class PredictorBrowserTest : public InProcessBrowserTest {
EXPECT_TRUE(test_server->FlushAllSocketsAndConnectionsOnUIThread());
}
+ void ExpectFoundUrlsOnUIThread(
+ const network_hints::UrlList& found_names,
+ const network_hints::UrlList& not_found_names) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&PredictorBrowserTest::ExpectFoundUrls,
+ this, found_names, not_found_names));
+ }
+ void ExpectFoundUrls(const network_hints::UrlList& found_names,
+ const network_hints::UrlList& not_found_names) {
+ for (const auto& name : found_names) {
+ EXPECT_TRUE(predictor()->WasFound(name)) << "Expected to have found "
+ << name.spec();
+ }
+ for (const auto& name : not_found_names) {
+ EXPECT_FALSE(predictor()->WasFound(name)) << "Did not expect to find "
+ << name.spec();
+ }
+ }
+
+ void DiscardAllResultsOnUIThread() {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&Predictor::DiscardAllResults,
+ base::Unretained(predictor())));
+ }
+
CrossSitePredictorObserver* observer() { return observer_.get(); }
// Navigate to an html file on embedded_test_server and tell it to request
@@ -669,6 +757,7 @@ class PredictorBrowserTest : public InProcessBrowserTest {
std::unique_ptr<ConnectionListener> cross_site_connection_listener_;
private:
+ scoped_refptr<net::RuleBasedHostResolverProc> rule_based_resolver_proc_;
scoped_refptr<HostResolutionRequestRecorder>
host_resolution_request_recorder_;
std::unique_ptr<net::ScopedDefaultHostResolverProc>
@@ -678,6 +767,84 @@ class PredictorBrowserTest : public InProcessBrowserTest {
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
+IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SingleLookupTest) {
+ DiscardAllResultsOnUIThread();
+
+ GURL goog("http://www.example.test:80");
+
+ network_hints::UrlList names{goog};
+
+ // Try to flood the predictor with many concurrent requests.
+ FloodResolveRequestsOnUIThread(names);
+ WaitUntilHostNamesHaveBeenRequested(names);
+ base::MessageLoop::current()->RunUntilIdle();
+ ExpectFoundUrlsOnUIThread(names, network_hints::UrlList());
+
+ EXPECT_GT(predictor()->peak_pending_lookups(), names.size() / 2);
+ EXPECT_LE(predictor()->peak_pending_lookups(), names.size());
+ EXPECT_LE(predictor()->peak_pending_lookups(),
+ predictor()->max_concurrent_dns_lookups());
+}
+
+IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ConcurrentLookupTest) {
+ DiscardAllResultsOnUIThread();
+
+ GURL goog("http://www.example.test:80"), goog2("http://gmail.google.com:80"),
+ goog3("http://mail.google.com:80"), goog4("http://gmail.com:80");
+ GURL bad1("http://bad1.notfound:80"), bad2("http://bad2.notfound:80");
+
+ UrlList found_names{goog, goog3, goog2, goog4, goog};
+ UrlList not_found_names{bad1, bad2};
+
+ FloodResolveRequestsOnUIThread(found_names);
+ FloodResolveRequestsOnUIThread(not_found_names);
+ WaitUntilHostNamesHaveBeenRequested(found_names);
+ WaitUntilHostNamesHaveBeenRequested(not_found_names);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ ExpectFoundUrlsOnUIThread(found_names, not_found_names);
+
+ EXPECT_LE(predictor()->peak_pending_lookups(),
+ found_names.size() + not_found_names.size());
+ EXPECT_LE(predictor()->peak_pending_lookups(),
+ predictor()->max_concurrent_dns_lookups());
+}
+
+IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, MassiveConcurrentLookupTest) {
+ DiscardAllResultsOnUIThread();
+ UrlList not_found_names;
+ for (int i = 0; i < 100; i++) {
+ not_found_names.push_back(
+ GURL(base::StringPrintf("http://host%d.notfound:80", i)));
+ }
+ FloodResolveRequestsOnUIThread(not_found_names);
+ WaitUntilHostNamesHaveBeenRequested(not_found_names);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ ExpectFoundUrlsOnUIThread(network_hints::UrlList(), not_found_names);
+
+ EXPECT_LE(predictor()->peak_pending_lookups(), not_found_names.size());
+
+ EXPECT_LE(predictor()->peak_pending_lookups(),
+ predictor()->max_concurrent_dns_lookups());
+}
+
+IN_PROC_BROWSER_TEST_F(PredictorBrowserTest,
+ ShutdownWhenResolutionIsPendingTest) {
+ GURL localhost("http://delay.google.com:80");
+ UrlList names;
+ names.push_back(localhost);
+
+ // Flood with delayed requests.
+ FloodResolveRequestsOnUIThread(names);
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
+ base::TimeDelta::FromMilliseconds(500));
+ base::MessageLoop::current()->Run();
+
+ EXPECT_FALSE(predictor()->WasFound(localhost));
+}
+
IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, SimplePreconnectOne) {
predictor()->PreconnectUrl(
embedded_test_server()->base_url(), GURL(),
@@ -1132,17 +1299,14 @@ IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCyclePreresolve) {
WaitUntilHostHasBeenRequested(target_url_.host());
}
-// Flaky on Windows: http://crbug.com/469120
-#if defined(OS_WIN)
-#define MAYBE_DnsPrefetch DISABLED_DnsPrefetch
-#else
-#define MAYBE_DnsPrefetch DnsPrefetch
-#endif
-IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, MAYBE_DnsPrefetch) {
+IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, DnsPrefetch) {
+ // Navigate once to make sure all initial hostnames are requested.
+ ui_test_utils::NavigateToURL(browser(),
+ embedded_test_server()->GetURL("/title1.html"));
+
int hostnames_requested_before_load = RequestedHostnameCount();
- ui_test_utils::NavigateToURL(
- browser(),
- GURL(embedded_test_server()->GetURL("/predictor/dns_prefetch.html")));
+ ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL(
+ "/predictor/dns_prefetch.html"));
WaitUntilHostHasBeenRequested(kChromiumHostname);
ASSERT_FALSE(HasHostBeenRequested(kInvalidLongHostname));
ASSERT_EQ(hostnames_requested_before_load + 1, RequestedHostnameCount());

Powered by Google App Engine
This is Rietveld 408576698