Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" | 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" |
| 6 | 6 |
| 7 #include <iostream> | 7 #include <iostream> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
| 14 #include "base/test/histogram_tester.h" | 14 #include "base/test/histogram_tester.h" |
| 15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 16 #include "chrome/browser/history/history_service_factory.h" | 16 #include "chrome/browser/history/history_service_factory.h" |
| 17 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" | 17 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" |
| 18 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h" | 18 #include "chrome/browser/predictors/resource_prefetch_predictor_test_util.h" |
| 19 #include "chrome/browser/predictors/resource_prefetcher_manager.h" | |
| 19 #include "chrome/test/base/testing_profile.h" | 20 #include "chrome/test/base/testing_profile.h" |
| 20 #include "components/history/core/browser/history_service.h" | 21 #include "components/history/core/browser/history_service.h" |
| 21 #include "components/history/core/browser/history_types.h" | 22 #include "components/history/core/browser/history_types.h" |
| 22 #include "components/sessions/core/session_id.h" | 23 #include "components/sessions/core/session_id.h" |
| 23 #include "content/public/browser/resource_request_info.h" | 24 #include "content/public/browser/resource_request_info.h" |
| 24 #include "content/public/test/test_browser_thread_bundle.h" | 25 #include "content/public/test/test_browser_thread_bundle.h" |
| 25 #include "net/http/http_response_headers.h" | 26 #include "net/http/http_response_headers.h" |
| 26 #include "net/url_request/url_request_context.h" | 27 #include "net/url_request/url_request_context.h" |
| 27 #include "net/url_request/url_request_job.h" | 28 #include "net/url_request/url_request_job.h" |
| 28 #include "net/url_request/url_request_test_util.h" | 29 #include "net/url_request/url_request_test_util.h" |
| 29 #include "testing/gmock/include/gmock/gmock.h" | 30 #include "testing/gmock/include/gmock/gmock.h" |
| 30 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
| 31 | 32 |
| 32 using testing::ContainerEq; | 33 using testing::ContainerEq; |
| 33 using testing::Pointee; | 34 using testing::Pointee; |
| 34 using testing::SetArgPointee; | 35 using testing::SetArgPointee; |
| 35 using testing::StrictMock; | 36 using testing::StrictMock; |
| 36 using testing::UnorderedElementsAre; | 37 using testing::UnorderedElementsAre; |
| 37 | 38 |
| 38 namespace predictors { | 39 namespace predictors { |
| 39 | 40 |
| 41 namespace { | |
| 42 constexpr int kDefaultMode = LoadingPredictorConfig::LEARNING | | |
| 43 LoadingPredictorConfig::PREFETCHING_FOR_EXTERNAL; | |
| 44 } // namespace | |
| 45 | |
| 40 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; | 46 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; |
| 41 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; | 47 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; |
| 42 using PrefetchDataMap = ResourcePrefetchPredictorTables::PrefetchDataMap; | 48 using PrefetchDataMap = ResourcePrefetchPredictorTables::PrefetchDataMap; |
| 43 using RedirectDataMap = ResourcePrefetchPredictorTables::RedirectDataMap; | 49 using RedirectDataMap = ResourcePrefetchPredictorTables::RedirectDataMap; |
| 44 using ManifestDataMap = ResourcePrefetchPredictorTables::ManifestDataMap; | 50 using ManifestDataMap = ResourcePrefetchPredictorTables::ManifestDataMap; |
| 45 using OriginDataMap = ResourcePrefetchPredictorTables::OriginDataMap; | 51 using OriginDataMap = ResourcePrefetchPredictorTables::OriginDataMap; |
| 46 | 52 |
| 47 scoped_refptr<net::HttpResponseHeaders> MakeResponseHeaders( | 53 scoped_refptr<net::HttpResponseHeaders> MakeResponseHeaders( |
| 48 const char* headers) { | 54 const char* headers) { |
| 49 return make_scoped_refptr(new net::HttpResponseHeaders( | 55 return make_scoped_refptr(new net::HttpResponseHeaders( |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 explicit MockResourcePrefetchPredictorObserver( | 173 explicit MockResourcePrefetchPredictorObserver( |
| 168 ResourcePrefetchPredictor* predictor) | 174 ResourcePrefetchPredictor* predictor) |
| 169 : TestObserver(predictor) {} | 175 : TestObserver(predictor) {} |
| 170 | 176 |
| 171 MOCK_METHOD2( | 177 MOCK_METHOD2( |
| 172 OnNavigationLearned, | 178 OnNavigationLearned, |
| 173 void(size_t url_visit_count, | 179 void(size_t url_visit_count, |
| 174 const ResourcePrefetchPredictor::PageRequestSummary& summary)); | 180 const ResourcePrefetchPredictor::PageRequestSummary& summary)); |
| 175 }; | 181 }; |
| 176 | 182 |
| 183 // Does nothing when a prefetch starts. | |
| 184 class MockResourcePrefetcherManager : public ResourcePrefetcherManager { | |
| 185 public: | |
| 186 using ResourcePrefetcherManager::ResourcePrefetcherManager; | |
| 187 MOCK_METHOD2(MaybeAddPrefetch, | |
| 188 void(const GURL& main_frame_url, const std::vector<GURL>& urls)); | |
| 189 | |
| 190 protected: | |
| 191 ~MockResourcePrefetcherManager() {} | |
| 192 | |
| 193 private: | |
| 194 DISALLOW_COPY_AND_ASSIGN(MockResourcePrefetcherManager); | |
| 195 }; | |
| 196 | |
| 177 class ResourcePrefetchPredictorTest : public testing::Test { | 197 class ResourcePrefetchPredictorTest : public testing::Test { |
| 178 public: | 198 public: |
| 179 ResourcePrefetchPredictorTest(); | 199 ResourcePrefetchPredictorTest(); |
| 180 ~ResourcePrefetchPredictorTest() override; | 200 ~ResourcePrefetchPredictorTest() override; |
| 181 void SetUp() override; | 201 void SetUp() override; |
| 182 void TearDown() override; | 202 void TearDown() override; |
| 183 | 203 |
| 184 protected: | 204 protected: |
| 185 void AddUrlToHistory(const std::string& url, int visit_count) { | 205 void AddUrlToHistory(const std::string& url, int visit_count) { |
| 186 HistoryServiceFactory::GetForProfile(profile_.get(), | 206 HistoryServiceFactory::GetForProfile(profile_.get(), |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 false, true, content::PREVIEWS_OFF); | 240 false, true, content::PREVIEWS_OFF); |
| 221 request->Start(); | 241 request->Start(); |
| 222 return request; | 242 return request; |
| 223 } | 243 } |
| 224 | 244 |
| 225 void InitializePredictor() { | 245 void InitializePredictor() { |
| 226 predictor_->StartInitialization(); | 246 predictor_->StartInitialization(); |
| 227 base::RunLoop loop; | 247 base::RunLoop loop; |
| 228 loop.RunUntilIdle(); // Runs the DB lookup. | 248 loop.RunUntilIdle(); // Runs the DB lookup. |
| 229 profile_->BlockUntilHistoryProcessesPendingRequests(); | 249 profile_->BlockUntilHistoryProcessesPendingRequests(); |
| 250 | |
| 251 mock_prefetch_manager_ = nullptr; | |
| 252 if (predictor_->prefetch_manager_) { | |
| 253 mock_prefetch_manager_ = new StrictMock<MockResourcePrefetcherManager>( | |
| 254 predictor_.get(), predictor_->config_, | |
| 255 predictor_->profile_->GetRequestContext()); | |
| 256 predictor_->set_mock_resource_prefetcher_manager(mock_prefetch_manager_); | |
| 257 } | |
| 230 } | 258 } |
| 231 | 259 |
| 232 void ResetPredictor() { | 260 void ResetPredictor(int mode = kDefaultMode) { |
|
alexilin
2017/05/23 11:01:39
It changes the current behavior of tests. Why not
Benoit L
2017/05/29 16:45:14
Done.
| |
| 233 LoadingPredictorConfig config; | 261 LoadingPredictorConfig config; |
| 234 config.max_urls_to_track = 3; | 262 config.max_urls_to_track = 3; |
| 235 config.max_hosts_to_track = 2; | 263 config.max_hosts_to_track = 2; |
| 236 config.min_url_visit_count = 2; | 264 config.min_url_visit_count = 2; |
| 237 config.max_resources_per_entry = 4; | 265 config.max_resources_per_entry = 4; |
| 238 config.max_consecutive_misses = 2; | 266 config.max_consecutive_misses = 2; |
| 239 config.max_redirect_consecutive_misses = 2; | 267 config.max_redirect_consecutive_misses = 2; |
| 240 config.min_resource_confidence_to_trigger_prefetch = 0.5; | 268 config.min_resource_confidence_to_trigger_prefetch = 0.5; |
| 241 config.is_url_learning_enabled = true; | 269 config.is_url_learning_enabled = true; |
| 242 config.is_manifests_enabled = true; | 270 config.is_manifests_enabled = true; |
| 243 config.is_origin_learning_enabled = true; | 271 config.is_origin_learning_enabled = true; |
| 272 config.mode = mode; | |
| 244 | 273 |
| 245 config.mode |= LoadingPredictorConfig::LEARNING; | 274 predictor_ = |
| 246 predictor_.reset(new ResourcePrefetchPredictor(config, profile_.get())); | 275 base::MakeUnique<ResourcePrefetchPredictor>(config, profile_.get()); |
| 247 predictor_->set_mock_tables(mock_tables_); | 276 predictor_->set_mock_tables(mock_tables_); |
| 248 } | 277 } |
| 249 | 278 |
| 250 void InitializeSampleData(); | 279 void InitializeSampleData(); |
| 251 void TestRedirectStatusHistogram( | 280 void TestRedirectStatusHistogram( |
| 252 const std::string& predictor_initial_key, | 281 const std::string& predictor_initial_key, |
| 253 const std::string& predictor_key, | 282 const std::string& predictor_key, |
| 254 const std::string& navigation_initial_url, | 283 const std::string& navigation_initial_url, |
| 255 const std::string& navigation_url, | 284 const std::string& navigation_url, |
| 256 ResourcePrefetchPredictor::RedirectStatus expected_status); | 285 ResourcePrefetchPredictor::RedirectStatus expected_status); |
| 257 | 286 |
| 258 content::TestBrowserThreadBundle thread_bundle_; | 287 content::TestBrowserThreadBundle thread_bundle_; |
| 259 std::unique_ptr<TestingProfile> profile_; | 288 std::unique_ptr<TestingProfile> profile_; |
| 260 net::TestURLRequestContext url_request_context_; | 289 net::TestURLRequestContext url_request_context_; |
| 261 | 290 |
| 262 std::unique_ptr<ResourcePrefetchPredictor> predictor_; | 291 std::unique_ptr<ResourcePrefetchPredictor> predictor_; |
| 263 scoped_refptr<StrictMock<MockResourcePrefetchPredictorTables>> mock_tables_; | 292 scoped_refptr<StrictMock<MockResourcePrefetchPredictorTables>> mock_tables_; |
| 293 scoped_refptr<StrictMock<MockResourcePrefetcherManager>> | |
| 294 mock_prefetch_manager_; | |
| 264 | 295 |
| 265 PrefetchDataMap test_url_data_; | 296 PrefetchDataMap test_url_data_; |
| 266 PrefetchDataMap test_host_data_; | 297 PrefetchDataMap test_host_data_; |
| 267 RedirectDataMap test_url_redirect_data_; | 298 RedirectDataMap test_url_redirect_data_; |
| 268 RedirectDataMap test_host_redirect_data_; | 299 RedirectDataMap test_host_redirect_data_; |
| 269 ManifestDataMap test_manifest_data_; | 300 ManifestDataMap test_manifest_data_; |
| 270 OriginDataMap test_origin_data_; | 301 OriginDataMap test_origin_data_; |
| 271 | 302 |
| 272 MockURLRequestJobFactory url_request_job_factory_; | 303 MockURLRequestJobFactory url_request_job_factory_; |
| 273 EmptyURLRequestDelegate url_request_delegate_; | 304 EmptyURLRequestDelegate url_request_delegate_; |
| (...skipping 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2088 | 2119 |
| 2089 TEST_F(ResourcePrefetchPredictorTest, | 2120 TEST_F(ResourcePrefetchPredictorTest, |
| 2090 TestRedirectStatusRedirectCorrectlyPredicted) { | 2121 TestRedirectStatusRedirectCorrectlyPredicted) { |
| 2091 TestRedirectStatusHistogram( | 2122 TestRedirectStatusHistogram( |
| 2092 "google.com", "www.google.com", "http://google.com?query=cats", | 2123 "google.com", "www.google.com", "http://google.com?query=cats", |
| 2093 "http://www.google.com?query=cats", | 2124 "http://www.google.com?query=cats", |
| 2094 ResourcePrefetchPredictor::RedirectStatus::REDIRECT_CORRECTLY_PREDICTED); | 2125 ResourcePrefetchPredictor::RedirectStatus::REDIRECT_CORRECTLY_PREDICTED); |
| 2095 } | 2126 } |
| 2096 | 2127 |
| 2097 TEST_F(ResourcePrefetchPredictorTest, TestPrefetchingDurationHistogram) { | 2128 TEST_F(ResourcePrefetchPredictorTest, TestPrefetchingDurationHistogram) { |
| 2098 // Prefetching duration for an url without resources in the database | 2129 // Fill the database to record a duration. |
|
alexilin
2017/05/23 11:01:39
Why changing this test?
We wanted to record prefet
| |
| 2099 // shouldn't be recorded. | 2130 for (const auto& kv : test_host_data_) |
|
alexilin
2017/05/23 11:01:39
nit:
predictor_->host_table_cache_ = test_host_dat
| |
| 2100 const std::string main_frame_url = "http://google.com/?query=cats"; | 2131 predictor_->host_table_cache_->insert(kv); |
| 2101 predictor_->StartPrefetching(GURL(main_frame_url), HintOrigin::EXTERNAL); | |
| 2102 predictor_->StopPrefetching(GURL(main_frame_url)); | |
| 2103 histogram_tester_->ExpectTotalCount( | |
| 2104 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 0); | |
| 2105 | 2132 |
| 2106 // Fill the database to record a duration. | 2133 using testing::_; |
| 2107 PrefetchData google = CreatePrefetchData("google.com", 1); | 2134 EXPECT_CALL(*mock_prefetch_manager_.get(), MaybeAddPrefetch(_, _)); |
| 2108 InitializeResourceData( | |
| 2109 google.add_resources(), "https://cdn.google.com/script.js", | |
| 2110 content::RESOURCE_TYPE_SCRIPT, 10, 0, 1, 2.1, net::MEDIUM, false, false); | |
| 2111 predictor_->host_table_cache_->insert( | |
| 2112 std::make_pair(google.primary_key(), google)); | |
| 2113 | 2135 |
| 2114 predictor_->StartPrefetching(GURL(main_frame_url), HintOrigin::EXTERNAL); | 2136 const GURL url = GURL("http://www.facebook.com/cats"); |
| 2115 predictor_->StopPrefetching(GURL(main_frame_url)); | 2137 predictor_->StartPrefetching(url, HintOrigin::EXTERNAL); |
| 2138 predictor_->StopPrefetching(url); | |
| 2116 histogram_tester_->ExpectTotalCount( | 2139 histogram_tester_->ExpectTotalCount( |
| 2117 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 1); | 2140 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, 1); |
| 2118 } | 2141 } |
| 2119 | 2142 |
| 2120 TEST_F(ResourcePrefetchPredictorTest, TestRecordFirstContentfulPaint) { | 2143 TEST_F(ResourcePrefetchPredictorTest, TestRecordFirstContentfulPaint) { |
| 2121 using testing::_; | 2144 using testing::_; |
| 2122 EXPECT_CALL(*mock_tables_.get(), UpdateRedirectData(_, _)); | 2145 EXPECT_CALL(*mock_tables_.get(), UpdateRedirectData(_, _)); |
| 2123 EXPECT_CALL(*mock_tables_.get(), UpdateOriginData(_)); | 2146 EXPECT_CALL(*mock_tables_.get(), UpdateOriginData(_)); |
| 2124 | 2147 |
| 2125 auto res1_time = base::TimeTicks::FromInternalValue(1); | 2148 auto res1_time = base::TimeTicks::FromInternalValue(1); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2163 content::RESOURCE_TYPE_SCRIPT, 1, 0, 0, 3.0, | 2186 content::RESOURCE_TYPE_SCRIPT, 1, 0, 0, 3.0, |
| 2164 net::MEDIUM, false, false); | 2187 net::MEDIUM, false, false); |
| 2165 resource3_rd->set_before_first_contentful_paint(false); | 2188 resource3_rd->set_before_first_contentful_paint(false); |
| 2166 EXPECT_CALL(*mock_tables_.get(), | 2189 EXPECT_CALL(*mock_tables_.get(), |
| 2167 UpdateResourceData(host_data, PREFETCH_KEY_TYPE_HOST)); | 2190 UpdateResourceData(host_data, PREFETCH_KEY_TYPE_HOST)); |
| 2168 | 2191 |
| 2169 predictor_->RecordMainFrameLoadComplete(main_frame.navigation_id); | 2192 predictor_->RecordMainFrameLoadComplete(main_frame.navigation_id); |
| 2170 profile_->BlockUntilHistoryProcessesPendingRequests(); | 2193 profile_->BlockUntilHistoryProcessesPendingRequests(); |
| 2171 } | 2194 } |
| 2172 | 2195 |
| 2196 TEST_F(ResourcePrefetchPredictorTest, TestCanPrefetchUrlForOrigin) { | |
| 2197 for (const auto& kv : test_host_data_) | |
|
alexilin
2017/05/23 11:01:39
ditto
| |
| 2198 predictor_->host_table_cache_->insert(kv); | |
| 2199 | |
| 2200 const GURL url = GURL("http://www.facebook.com/cats"); | |
| 2201 EXPECT_TRUE(predictor_->CanPrefetchUrlForOrigin(url, HintOrigin::EXTERNAL)); | |
| 2202 | |
| 2203 // Unknown host. | |
| 2204 EXPECT_FALSE(predictor_->CanPrefetchUrlForOrigin(GURL("https://unknown.com"), | |
| 2205 HintOrigin::EXTERNAL)); | |
| 2206 // Wrong origin. | |
| 2207 EXPECT_FALSE( | |
| 2208 predictor_->CanPrefetchUrlForOrigin(url, HintOrigin::NAVIGATION)); | |
| 2209 | |
| 2210 // Prefetching not enabled. | |
| 2211 EXPECT_CALL(*mock_tables_.get(), | |
| 2212 GetAllData(Pointee(ContainerEq(PrefetchDataMap())), | |
| 2213 Pointee(ContainerEq(PrefetchDataMap())), | |
| 2214 Pointee(ContainerEq(RedirectDataMap())), | |
| 2215 Pointee(ContainerEq(RedirectDataMap())), | |
| 2216 Pointee(ContainerEq(ManifestDataMap())), | |
| 2217 Pointee(ContainerEq(OriginDataMap())))); | |
| 2218 ResetPredictor(LoadingPredictorConfig::LEARNING); | |
| 2219 InitializePredictor(); | |
| 2220 for (const auto& kv : test_host_data_) | |
|
alexilin
2017/05/23 11:01:39
ditto
| |
| 2221 predictor_->host_table_cache_->insert(kv); | |
| 2222 | |
| 2223 EXPECT_FALSE(predictor_->CanPrefetchUrlForOrigin(url, HintOrigin::EXTERNAL)); | |
| 2224 } | |
| 2225 | |
| 2173 } // namespace predictors | 2226 } // namespace predictors |
| OLD | NEW |