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

Side by Side Diff: components/ntp_snippets/ntp_snippets_service_unittest.cc

Issue 2227973002: Add request throttler to thumbnail fetching for articles on mobile NTP (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: One forgotten comment Created 4 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "components/ntp_snippets/ntp_snippets_service.h" 5 #include "components/ntp_snippets/ntp_snippets_service.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility>
8 #include <vector> 9 #include <vector>
9 10
10 #include "base/command_line.h" 11 #include "base/command_line.h"
11 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
12 #include "base/files/scoped_temp_dir.h" 13 #include "base/files/scoped_temp_dir.h"
13 #include "base/json/json_reader.h" 14 #include "base/json/json_reader.h"
14 #include "base/macros.h" 15 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
16 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h" 18 #include "base/run_loop.h"
18 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
21 #include "base/test/histogram_tester.h" 22 #include "base/test/histogram_tester.h"
22 #include "base/threading/thread_task_runner_handle.h" 23 #include "base/threading/thread_task_runner_handle.h"
23 #include "base/time/time.h" 24 #include "base/time/time.h"
24 #include "components/image_fetcher/image_decoder.h" 25 #include "components/image_fetcher/image_decoder.h"
25 #include "components/image_fetcher/image_fetcher.h" 26 #include "components/image_fetcher/image_fetcher.h"
27 #include "components/image_fetcher/image_fetcher_delegate.h"
26 #include "components/ntp_snippets/category_factory.h" 28 #include "components/ntp_snippets/category_factory.h"
27 #include "components/ntp_snippets/ntp_snippet.h" 29 #include "components/ntp_snippets/ntp_snippet.h"
28 #include "components/ntp_snippets/ntp_snippets_database.h" 30 #include "components/ntp_snippets/ntp_snippets_database.h"
29 #include "components/ntp_snippets/ntp_snippets_fetcher.h" 31 #include "components/ntp_snippets/ntp_snippets_fetcher.h"
30 #include "components/ntp_snippets/ntp_snippets_scheduler.h" 32 #include "components/ntp_snippets/ntp_snippets_scheduler.h"
31 #include "components/ntp_snippets/ntp_snippets_test_utils.h" 33 #include "components/ntp_snippets/ntp_snippets_test_utils.h"
32 #include "components/ntp_snippets/switches.h" 34 #include "components/ntp_snippets/switches.h"
33 #include "components/prefs/testing_pref_service.h" 35 #include "components/prefs/testing_pref_service.h"
34 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" 36 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
35 #include "components/signin/core/browser/fake_signin_manager.h" 37 #include "components/signin/core/browser/fake_signin_manager.h"
36 #include "google_apis/google_api_keys.h" 38 #include "google_apis/google_api_keys.h"
37 #include "net/url_request/test_url_fetcher_factory.h" 39 #include "net/url_request/test_url_fetcher_factory.h"
38 #include "net/url_request/url_request_test_util.h" 40 #include "net/url_request/url_request_test_util.h"
39 #include "testing/gmock/include/gmock/gmock.h" 41 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/gtest/include/gtest/gtest.h" 42 #include "testing/gtest/include/gtest/gtest.h"
43 #include "ui/gfx/image/image.h"
44 #include "ui/gfx/image/image_unittest_util.h"
41 45
46 using image_fetcher::ImageFetcher;
47 using image_fetcher::ImageFetcherDelegate;
42 using testing::ElementsAre; 48 using testing::ElementsAre;
43 using testing::Eq; 49 using testing::Eq;
44 using testing::Invoke; 50 using testing::Invoke;
45 using testing::IsEmpty; 51 using testing::IsEmpty;
46 using testing::Mock; 52 using testing::Mock;
47 using testing::Return; 53 using testing::Return;
48 using testing::SizeIs; 54 using testing::SizeIs;
49 using testing::StartsWith; 55 using testing::StartsWith;
50 using testing::_; 56 using testing::_;
51 57
(...skipping 10 matching lines...) Expand all
62 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s"; 68 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s";
63 69
64 const char kSnippetUrl[] = "http://localhost/foobar"; 70 const char kSnippetUrl[] = "http://localhost/foobar";
65 const char kSnippetTitle[] = "Title"; 71 const char kSnippetTitle[] = "Title";
66 const char kSnippetText[] = "Snippet"; 72 const char kSnippetText[] = "Snippet";
67 const char kSnippetSalientImage[] = "http://localhost/salient_image"; 73 const char kSnippetSalientImage[] = "http://localhost/salient_image";
68 const char kSnippetPublisherName[] = "Foo News"; 74 const char kSnippetPublisherName[] = "Foo News";
69 const char kSnippetAmpUrl[] = "http://localhost/amp"; 75 const char kSnippetAmpUrl[] = "http://localhost/amp";
70 const float kSnippetScore = 5.0; 76 const float kSnippetScore = 5.0;
71 77
78 const char kSnippetUrl2[] = "http://foo.com/bar";
79
72 base::Time GetDefaultCreationTime() { 80 base::Time GetDefaultCreationTime() {
73 base::Time out_time; 81 base::Time out_time;
74 EXPECT_TRUE(base::Time::FromUTCExploded(kDefaultCreationTime, &out_time)); 82 EXPECT_TRUE(base::Time::FromUTCExploded(kDefaultCreationTime, &out_time));
75 return out_time; 83 return out_time;
76 } 84 }
77 85
78 base::Time GetDefaultExpirationTime() { 86 base::Time GetDefaultExpirationTime() {
79 return base::Time::Now() + base::TimeDelta::FromHours(1); 87 return base::Time::Now() + base::TimeDelta::FromHours(1);
80 } 88 }
81 89
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 // fail to parse as snippets. 192 // fail to parse as snippets.
185 size_t pos = json_str.find("\"url\""); 193 size_t pos = json_str.find("\"url\"");
186 if (pos == std::string::npos) { 194 if (pos == std::string::npos) {
187 NOTREACHED(); 195 NOTREACHED();
188 return std::string(); 196 return std::string();
189 } 197 }
190 json_str[pos + 1] = 'x'; 198 json_str[pos + 1] = 'x';
191 return json_str; 199 return json_str;
192 } 200 }
193 201
202 void ServeOneByOneImage(
203 const std::string& id,
204 base::Callback<void(const std::string&, const gfx::Image&)> callback) {
205 base::ThreadTaskRunnerHandle::Get()->PostTask(
206 FROM_HERE, base::Bind(callback, id, gfx::test::CreateImage(1, 1)));
207 }
208
194 void ParseJson( 209 void ParseJson(
195 const std::string& json, 210 const std::string& json,
196 const ntp_snippets::NTPSnippetsFetcher::SuccessCallback& success_callback, 211 const ntp_snippets::NTPSnippetsFetcher::SuccessCallback& success_callback,
197 const ntp_snippets::NTPSnippetsFetcher::ErrorCallback& error_callback) { 212 const ntp_snippets::NTPSnippetsFetcher::ErrorCallback& error_callback) {
198 base::JSONReader json_reader; 213 base::JSONReader json_reader;
199 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); 214 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json);
200 if (value) { 215 if (value) {
201 success_callback.Run(std::move(value)); 216 success_callback.Run(std::move(value));
202 } else { 217 } else {
203 error_callback.Run(json_reader.GetErrorMessage()); 218 error_callback.Run(json_reader.GetErrorMessage());
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 EXPECT_EQ(new_status, CategoryStatus::AVAILABLE_LOADING); 271 EXPECT_EQ(new_status, CategoryStatus::AVAILABLE_LOADING);
257 run_loop_.Quit(); 272 run_loop_.Quit();
258 } 273 }
259 274
260 MockProviderObserver* observer_; 275 MockProviderObserver* observer_;
261 base::RunLoop run_loop_; 276 base::RunLoop run_loop_;
262 277
263 DISALLOW_COPY_AND_ASSIGN(WaitForDBLoad); 278 DISALLOW_COPY_AND_ASSIGN(WaitForDBLoad);
264 }; 279 };
265 280
281 class MockImageFetcher : public ImageFetcher {
282 public:
283 MOCK_METHOD1(SetImageFetcherDelegate, void(ImageFetcherDelegate*));
284 MOCK_METHOD1(SetDataUseServiceName, void(DataUseServiceName));
285 MOCK_METHOD3(
286 StartOrQueueNetworkRequest,
287 void(const std::string&,
288 const GURL&,
289 base::Callback<void(const std::string&, const gfx::Image&)>));
290 };
291
266 } // namespace 292 } // namespace
267 293
268 class NTPSnippetsServiceTest : public test::NTPSnippetsTestBase { 294 class NTPSnippetsServiceTest : public test::NTPSnippetsTestBase {
269 public: 295 public:
270 NTPSnippetsServiceTest() 296 NTPSnippetsServiceTest()
271 : fake_url_fetcher_factory_( 297 : fake_url_fetcher_factory_(
272 /*default_factory=*/&failing_url_fetcher_factory_), 298 /*default_factory=*/&failing_url_fetcher_factory_),
273 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, 299 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat,
274 google_apis::GetAPIKey().c_str())) { 300 google_apis::GetAPIKey().c_str())) {
275 NTPSnippetsService::RegisterProfilePrefs(pref_service()->registry()); 301 NTPSnippetsService::RegisterProfilePrefs(pref_service()->registry());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 base::MakeUnique<NTPSnippetsFetcher>( 344 base::MakeUnique<NTPSnippetsFetcher>(
319 fake_signin_manager(), fake_token_service_.get(), 345 fake_signin_manager(), fake_token_service_.get(),
320 std::move(request_context_getter), pref_service(), 346 std::move(request_context_getter), pref_service(),
321 &category_factory_, base::Bind(&ParseJson), 347 &category_factory_, base::Bind(&ParseJson),
322 /*is_stable_channel=*/true); 348 /*is_stable_channel=*/true);
323 349
324 fake_signin_manager()->SignIn("foo@bar.com"); 350 fake_signin_manager()->SignIn("foo@bar.com");
325 snippets_fetcher->SetPersonalizationForTesting( 351 snippets_fetcher->SetPersonalizationForTesting(
326 NTPSnippetsFetcher::Personalization::kNonPersonal); 352 NTPSnippetsFetcher::Personalization::kNonPersonal);
327 353
354 auto image_fetcher =
355 base::MakeUnique<testing::NiceMock<MockImageFetcher>>();
356 image_fetcher_ = image_fetcher.get();
357
328 // Add an initial fetch response, as the service tries to fetch when there 358 // Add an initial fetch response, as the service tries to fetch when there
329 // is nothing in the DB. 359 // is nothing in the DB.
330 SetUpFetchResponse(GetTestJson({GetSnippet()})); 360 SetUpFetchResponse(GetTestJson({GetSnippet()}));
331 361
332 service_.reset(new NTPSnippetsService( 362 service_.reset(new NTPSnippetsService(
333 &observer_, &category_factory_, pref_service(), nullptr, "fr", 363 &observer_, &category_factory_, pref_service(), nullptr, "fr",
334 &scheduler_, std::move(snippets_fetcher), /*image_fetcher=*/nullptr, 364 &scheduler_, std::move(snippets_fetcher),
335 /*image_fetcher=*/nullptr, base::MakeUnique<NTPSnippetsDatabase>( 365 std::move(image_fetcher), /*image_decoder=*/nullptr,
336 database_dir_.path(), task_runner), 366 base::MakeUnique<NTPSnippetsDatabase>(database_dir_.path(),
367 task_runner),
337 base::MakeUnique<NTPSnippetsStatusService>(fake_signin_manager(), 368 base::MakeUnique<NTPSnippetsStatusService>(fake_signin_manager(),
338 pref_service()))); 369 pref_service())));
339 370
340 WaitForDBLoad(&observer_, service_.get()); 371 WaitForDBLoad(&observer_, service_.get());
341 } 372 }
342 373
343 std::string MakeUniqueID(const std::string& within_category_id) { 374 std::string MakeUniqueID(const std::string& within_category_id) {
344 return service()->MakeUniqueID(articles_category(), within_category_id); 375 return service()->MakeUniqueID(articles_category(), within_category_id);
345 } 376 }
346 377
347 Category articles_category() { 378 Category articles_category() {
348 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES); 379 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES);
349 } 380 }
350 381
351 protected: 382 protected:
352 const GURL& test_url() { return test_url_; } 383 const GURL& test_url() { return test_url_; }
353 NTPSnippetsService* service() { return service_.get(); } 384 NTPSnippetsService* service() { return service_.get(); }
354 MockProviderObserver& observer() { return observer_; } 385 MockProviderObserver& observer() { return observer_; }
355 MockScheduler& mock_scheduler() { return scheduler_; } 386 MockScheduler& mock_scheduler() { return scheduler_; }
387 testing::NiceMock<MockImageFetcher>* image_fetcher() {
388 return image_fetcher_;
389 }
356 390
357 // Provide the json to be returned by the fake fetcher. 391 // Provide the json to be returned by the fake fetcher.
358 void SetUpFetchResponse(const std::string& json) { 392 void SetUpFetchResponse(const std::string& json) {
359 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK, 393 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK,
360 net::URLRequestStatus::SUCCESS); 394 net::URLRequestStatus::SUCCESS);
361 } 395 }
362 396
363 void LoadFromJSONString(const std::string& json) { 397 void LoadFromJSONString(const std::string& json) {
364 SetUpFetchResponse(json); 398 SetUpFetchResponse(json);
365 service()->FetchSnippets(true); 399 service()->FetchSnippets(true);
366 base::RunLoop().RunUntilIdle(); 400 base::RunLoop().RunUntilIdle();
367 } 401 }
368 402
369 private: 403 private:
370 base::MessageLoop message_loop_; 404 base::MessageLoop message_loop_;
371 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; 405 FailingFakeURLFetcherFactory failing_url_fetcher_factory_;
372 // Instantiation of factory automatically sets itself as URLFetcher's factory. 406 // Instantiation of factory automatically sets itself as URLFetcher's factory.
373 net::FakeURLFetcherFactory fake_url_fetcher_factory_; 407 net::FakeURLFetcherFactory fake_url_fetcher_factory_;
374 const GURL test_url_; 408 const GURL test_url_;
375 std::unique_ptr<OAuth2TokenService> fake_token_service_; 409 std::unique_ptr<OAuth2TokenService> fake_token_service_;
376 MockScheduler scheduler_; 410 MockScheduler scheduler_;
377 MockProviderObserver observer_; 411 MockProviderObserver observer_;
378 CategoryFactory category_factory_; 412 CategoryFactory category_factory_;
413 testing::NiceMock<MockImageFetcher>* image_fetcher_;
379 // Last so that the dependencies are deleted after the service. 414 // Last so that the dependencies are deleted after the service.
380 std::unique_ptr<NTPSnippetsService> service_; 415 std::unique_ptr<NTPSnippetsService> service_;
381 416
382 base::ScopedTempDir database_dir_; 417 base::ScopedTempDir database_dir_;
383 418
384 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); 419 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest);
385 }; 420 };
386 421
387 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) { 422 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) {
388 // SetUp() checks that Schedule is called. 423 // SetUp() checks that Schedule is called.
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE_LOADING)); 914 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE_LOADING));
880 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); 915 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1);
881 service()->OnDisabledReasonChanged(DisabledReason::NONE); 916 service()->OnDisabledReasonChanged(DisabledReason::NONE);
882 EXPECT_CALL(observer(), 917 EXPECT_CALL(observer(),
883 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE)); 918 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE));
884 base::RunLoop().RunUntilIdle(); 919 base::RunLoop().RunUntilIdle();
885 EXPECT_EQ(NTPSnippetsService::State::READY, service()->state_); 920 EXPECT_EQ(NTPSnippetsService::State::READY, service()->state_);
886 EXPECT_FALSE(service()->GetSnippetsForTesting().empty()); 921 EXPECT_FALSE(service()->GetSnippetsForTesting().empty());
887 } 922 }
888 923
924 TEST_F(NTPSnippetsServiceTest, ImageReturnedWithTheSameId) {
925 LoadFromJSONString(GetTestJson({GetSnippet()}));
926
927 gfx::Image image;
928 EXPECT_CALL(*image_fetcher(), StartOrQueueNetworkRequest(_, _, _))
929 .WillOnce(testing::WithArgs<0, 2>(Invoke(ServeOneByOneImage)));
930 testing::MockFunction<void(const std::string&, const gfx::Image&)>
931 image_fetched;
932 EXPECT_CALL(image_fetched, Call(MakeUniqueID(kSnippetUrl), _))
933 .WillOnce(testing::SaveArg<1>(&image));
934
935 service()->FetchSuggestionImage(
936 MakeUniqueID(kSnippetUrl),
937 base::Bind(&testing::MockFunction<void(const std::string&,
938 const gfx::Image&)>::Call,
939 base::Unretained(&image_fetched)));
940 base::RunLoop().RunUntilIdle();
941 // Check that the image by ServeOneByOneImage is really served.
942 EXPECT_EQ(1, image.Width());
943 }
944
945 TEST_F(NTPSnippetsServiceTest, EmptyImageReturnedForNonExistentId) {
946 gfx::Image image = gfx::test::CreateImage(1, 1);
tschumann 2016/08/16 14:56:55 please add a comment explaining that we set up the
jkrcal 2016/12/06 08:30:25 Done.
947 testing::MockFunction<void(const std::string&, const gfx::Image&)>
948 image_fetched;
949 EXPECT_CALL(image_fetched,
950 Call(MakeUniqueID(kSnippetUrl2), _))
951 .WillOnce(testing::SaveArg<1>(&image));
952
953 service()->FetchSuggestionImage(
954 MakeUniqueID(kSnippetUrl2),
955 base::Bind(&testing::MockFunction<void(const std::string&,
956 const gfx::Image&)>::Call,
957 base::Unretained(&image_fetched)));
958
959 base::RunLoop().RunUntilIdle();
960 EXPECT_TRUE(image.IsEmpty());
961 }
962
889 } // namespace ntp_snippets 963 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698