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

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: Tim's comments #2 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
« no previous file with comments | « components/ntp_snippets/ntp_snippets_service.cc ('k') | components/ntp_snippets/pref_names.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
41 44
45 using image_fetcher::ImageFetcher;
46 using image_fetcher::ImageFetcherDelegate;
42 using testing::ElementsAre; 47 using testing::ElementsAre;
43 using testing::Eq; 48 using testing::Eq;
44 using testing::Invoke; 49 using testing::Invoke;
45 using testing::IsEmpty; 50 using testing::IsEmpty;
46 using testing::Mock; 51 using testing::Mock;
47 using testing::Return; 52 using testing::Return;
48 using testing::SizeIs; 53 using testing::SizeIs;
49 using testing::StartsWith; 54 using testing::StartsWith;
50 using testing::_; 55 using testing::_;
51 56
(...skipping 10 matching lines...) Expand all
62 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s"; 67 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s";
63 68
64 const char kSnippetUrl[] = "http://localhost/foobar"; 69 const char kSnippetUrl[] = "http://localhost/foobar";
65 const char kSnippetTitle[] = "Title"; 70 const char kSnippetTitle[] = "Title";
66 const char kSnippetText[] = "Snippet"; 71 const char kSnippetText[] = "Snippet";
67 const char kSnippetSalientImage[] = "http://localhost/salient_image"; 72 const char kSnippetSalientImage[] = "http://localhost/salient_image";
68 const char kSnippetPublisherName[] = "Foo News"; 73 const char kSnippetPublisherName[] = "Foo News";
69 const char kSnippetAmpUrl[] = "http://localhost/amp"; 74 const char kSnippetAmpUrl[] = "http://localhost/amp";
70 const float kSnippetScore = 5.0; 75 const float kSnippetScore = 5.0;
71 76
77 const char kSnippetUrl2[] = "http://foo.com/bar";
78
72 base::Time GetDefaultCreationTime() { 79 base::Time GetDefaultCreationTime() {
73 base::Time out_time; 80 base::Time out_time;
74 EXPECT_TRUE(base::Time::FromUTCExploded(kDefaultCreationTime, &out_time)); 81 EXPECT_TRUE(base::Time::FromUTCExploded(kDefaultCreationTime, &out_time));
75 return out_time; 82 return out_time;
76 } 83 }
77 84
78 base::Time GetDefaultExpirationTime() { 85 base::Time GetDefaultExpirationTime() {
79 return base::Time::Now() + base::TimeDelta::FromHours(1); 86 return base::Time::Now() + base::TimeDelta::FromHours(1);
80 } 87 }
81 88
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 // fail to parse as snippets. 191 // fail to parse as snippets.
185 size_t pos = json_str.find("\"url\""); 192 size_t pos = json_str.find("\"url\"");
186 if (pos == std::string::npos) { 193 if (pos == std::string::npos) {
187 NOTREACHED(); 194 NOTREACHED();
188 return std::string(); 195 return std::string();
189 } 196 }
190 json_str[pos + 1] = 'x'; 197 json_str[pos + 1] = 'x';
191 return json_str; 198 return json_str;
192 } 199 }
193 200
201 void ServeEmptyImage(
202 const std::string& id,
203 base::Callback<void(const std::string&, const gfx::Image&)> callback) {
204 base::ThreadTaskRunnerHandle::Get()->PostTask(
205 FROM_HERE, base::Bind(callback, id, gfx::Image()));
206 }
207
194 void ParseJson( 208 void ParseJson(
195 const std::string& json, 209 const std::string& json,
196 const ntp_snippets::NTPSnippetsFetcher::SuccessCallback& success_callback, 210 const ntp_snippets::NTPSnippetsFetcher::SuccessCallback& success_callback,
197 const ntp_snippets::NTPSnippetsFetcher::ErrorCallback& error_callback) { 211 const ntp_snippets::NTPSnippetsFetcher::ErrorCallback& error_callback) {
198 base::JSONReader json_reader; 212 base::JSONReader json_reader;
199 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); 213 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json);
200 if (value) { 214 if (value) {
201 success_callback.Run(std::move(value)); 215 success_callback.Run(std::move(value));
202 } else { 216 } else {
203 error_callback.Run(json_reader.GetErrorMessage()); 217 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); 270 EXPECT_EQ(new_status, CategoryStatus::AVAILABLE_LOADING);
257 run_loop_.Quit(); 271 run_loop_.Quit();
258 } 272 }
259 273
260 MockProviderObserver* observer_; 274 MockProviderObserver* observer_;
261 base::RunLoop run_loop_; 275 base::RunLoop run_loop_;
262 276
263 DISALLOW_COPY_AND_ASSIGN(WaitForDBLoad); 277 DISALLOW_COPY_AND_ASSIGN(WaitForDBLoad);
264 }; 278 };
265 279
280 class MockImageFetcher : public ImageFetcher {
281 public:
282 MOCK_METHOD1(SetImageFetcherDelegate, void(ImageFetcherDelegate*));
283 MOCK_METHOD1(SetDataUseServiceName, void(DataUseServiceName));
284 MOCK_METHOD3(
285 StartOrQueueNetworkRequest,
286 void(const std::string&,
287 const GURL&,
288 base::Callback<void(const std::string&, const gfx::Image&)>));
289 };
290
266 } // namespace 291 } // namespace
267 292
268 class NTPSnippetsServiceTest : public test::NTPSnippetsTestBase { 293 class NTPSnippetsServiceTest : public test::NTPSnippetsTestBase {
269 public: 294 public:
270 NTPSnippetsServiceTest() 295 NTPSnippetsServiceTest()
271 : fake_url_fetcher_factory_( 296 : fake_url_fetcher_factory_(
272 /*default_factory=*/&failing_url_fetcher_factory_), 297 /*default_factory=*/&failing_url_fetcher_factory_),
273 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, 298 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat,
274 google_apis::GetAPIKey().c_str())) { 299 google_apis::GetAPIKey().c_str())) {
275 NTPSnippetsService::RegisterProfilePrefs(pref_service()->registry()); 300 NTPSnippetsService::RegisterProfilePrefs(pref_service()->registry());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 base::MakeUnique<NTPSnippetsFetcher>( 343 base::MakeUnique<NTPSnippetsFetcher>(
319 fake_signin_manager(), fake_token_service_.get(), 344 fake_signin_manager(), fake_token_service_.get(),
320 std::move(request_context_getter), pref_service(), 345 std::move(request_context_getter), pref_service(),
321 base::Bind(&ParseJson), 346 base::Bind(&ParseJson),
322 /*is_stable_channel=*/true); 347 /*is_stable_channel=*/true);
323 348
324 fake_signin_manager()->SignIn("foo@bar.com"); 349 fake_signin_manager()->SignIn("foo@bar.com");
325 snippets_fetcher->SetPersonalizationForTesting( 350 snippets_fetcher->SetPersonalizationForTesting(
326 NTPSnippetsFetcher::Personalization::kNonPersonal); 351 NTPSnippetsFetcher::Personalization::kNonPersonal);
327 352
353 auto image_fetcher =
tschumann 2016/08/12 12:37:09 nit: no need to allocate the mock on the heap. Sim
jkrcal 2016/08/16 12:31:43 I am a bit puzzled by this comment. I need to wr
Marc Treib 2016/08/16 13:29:18 I think Tim just didn't notice that you have to pa
tschumann 2016/08/16 14:56:55 yes to both. Actually I realized this later and *t
354 base::MakeUnique<testing::NiceMock<MockImageFetcher>>();
355 image_fetcher_ = image_fetcher.get();
356
328 // Add an initial fetch response, as the service tries to fetch when there 357 // Add an initial fetch response, as the service tries to fetch when there
329 // is nothing in the DB. 358 // is nothing in the DB.
330 SetUpFetchResponse(GetTestJson({GetSnippet()})); 359 SetUpFetchResponse(GetTestJson({GetSnippet()}));
331 360
332 service_.reset(new NTPSnippetsService( 361 service_.reset(new NTPSnippetsService(
333 &observer_, &category_factory_, pref_service(), nullptr, "fr", 362 &observer_, &category_factory_, pref_service(), nullptr, "fr",
334 &scheduler_, std::move(snippets_fetcher), /*image_fetcher=*/nullptr, 363 &scheduler_, std::move(snippets_fetcher),
335 /*image_fetcher=*/nullptr, base::MakeUnique<NTPSnippetsDatabase>( 364 std::move(image_fetcher), /*image_decoder=*/nullptr,
336 database_dir_.path(), task_runner), 365 base::MakeUnique<NTPSnippetsDatabase>(database_dir_.path(),
366 task_runner),
337 base::MakeUnique<NTPSnippetsStatusService>(fake_signin_manager(), 367 base::MakeUnique<NTPSnippetsStatusService>(fake_signin_manager(),
338 pref_service()))); 368 pref_service())));
339 369
340 WaitForDBLoad(&observer_, service_.get()); 370 WaitForDBLoad(&observer_, service_.get());
341 } 371 }
342 372
343 std::string MakeUniqueID(const std::string& within_category_id) { 373 std::string MakeUniqueID(const std::string& within_category_id) {
344 return service()->MakeUniqueID(articles_category(), within_category_id); 374 return service()->MakeUniqueID(articles_category(), within_category_id);
345 } 375 }
346 376
347 Category articles_category() { 377 Category articles_category() {
348 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES); 378 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES);
349 } 379 }
350 380
351 protected: 381 protected:
352 const GURL& test_url() { return test_url_; } 382 const GURL& test_url() { return test_url_; }
353 NTPSnippetsService* service() { return service_.get(); } 383 NTPSnippetsService* service() { return service_.get(); }
354 MockProviderObserver& observer() { return observer_; } 384 MockProviderObserver& observer() { return observer_; }
355 MockScheduler& mock_scheduler() { return scheduler_; } 385 MockScheduler& mock_scheduler() { return scheduler_; }
386 testing::NiceMock<MockImageFetcher>* image_fetcher() {
387 return image_fetcher_;
388 }
356 389
357 // Provide the json to be returned by the fake fetcher. 390 // Provide the json to be returned by the fake fetcher.
358 void SetUpFetchResponse(const std::string& json) { 391 void SetUpFetchResponse(const std::string& json) {
359 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK, 392 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK,
360 net::URLRequestStatus::SUCCESS); 393 net::URLRequestStatus::SUCCESS);
361 } 394 }
362 395
363 void LoadFromJSONString(const std::string& json) { 396 void LoadFromJSONString(const std::string& json) {
364 SetUpFetchResponse(json); 397 SetUpFetchResponse(json);
365 service()->FetchSnippets(true); 398 service()->FetchSnippets(true);
366 base::RunLoop().RunUntilIdle(); 399 base::RunLoop().RunUntilIdle();
367 } 400 }
368 401
369 private: 402 private:
370 base::MessageLoop message_loop_; 403 base::MessageLoop message_loop_;
371 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; 404 FailingFakeURLFetcherFactory failing_url_fetcher_factory_;
372 // Instantiation of factory automatically sets itself as URLFetcher's factory. 405 // Instantiation of factory automatically sets itself as URLFetcher's factory.
373 net::FakeURLFetcherFactory fake_url_fetcher_factory_; 406 net::FakeURLFetcherFactory fake_url_fetcher_factory_;
374 const GURL test_url_; 407 const GURL test_url_;
375 std::unique_ptr<OAuth2TokenService> fake_token_service_; 408 std::unique_ptr<OAuth2TokenService> fake_token_service_;
376 MockScheduler scheduler_; 409 MockScheduler scheduler_;
377 MockProviderObserver observer_; 410 MockProviderObserver observer_;
378 CategoryFactory category_factory_; 411 CategoryFactory category_factory_;
412 testing::NiceMock<MockImageFetcher>* image_fetcher_;
379 // Last so that the dependencies are deleted after the service. 413 // Last so that the dependencies are deleted after the service.
380 std::unique_ptr<NTPSnippetsService> service_; 414 std::unique_ptr<NTPSnippetsService> service_;
381 415
382 base::ScopedTempDir database_dir_; 416 base::ScopedTempDir database_dir_;
383 417
384 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); 418 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest);
385 }; 419 };
386 420
387 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) { 421 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) {
388 // SetUp() checks that Schedule is called. 422 // SetUp() checks that Schedule is called.
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE_LOADING)); 913 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE_LOADING));
880 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); 914 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1);
881 service()->OnDisabledReasonChanged(DisabledReason::NONE); 915 service()->OnDisabledReasonChanged(DisabledReason::NONE);
882 EXPECT_CALL(observer(), 916 EXPECT_CALL(observer(),
883 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE)); 917 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE));
884 base::RunLoop().RunUntilIdle(); 918 base::RunLoop().RunUntilIdle();
885 EXPECT_EQ(NTPSnippetsService::State::READY, service()->state_); 919 EXPECT_EQ(NTPSnippetsService::State::READY, service()->state_);
886 EXPECT_FALSE(service()->GetSnippetsForTesting().empty()); 920 EXPECT_FALSE(service()->GetSnippetsForTesting().empty());
887 } 921 }
888 922
923 TEST_F(NTPSnippetsServiceTest, ImageReturnedWithTheSameId) {
924 LoadFromJSONString(GetTestJson({GetSnippet()}));
925
926 EXPECT_CALL(*image_fetcher(), StartOrQueueNetworkRequest(_, _, _))
927 .Times(1)
tschumann 2016/08/12 12:37:09 Times(1) is implicit, you can remove that line. S
jkrcal 2016/08/16 12:31:43 Done.
928 .WillOnce(testing::WithArgs<0, 2>(Invoke(ServeEmptyImage)));
929 testing::MockFunction<void(const std::string&, const gfx::Image&)>
930 on_image_fetched_mock_function;
tschumann 2016/08/12 12:37:09 nit: feel free to pick shorter names (the test is
jkrcal 2016/08/16 12:31:43 Done.
931 EXPECT_CALL(on_image_fetched_mock_function,
932 Call(MakeUniqueID(kSnippetUrl), _))
933 .Times(1);
934
935 service()->FetchSuggestionImage(
936 MakeUniqueID(kSnippetUrl),
937 base::Bind(&testing::MockFunction<void(const std::string&,
938 const gfx::Image&)>::Call,
939 base::Unretained(&on_image_fetched_mock_function)));
940 base::RunLoop().RunUntilIdle();
941 }
942
943 TEST_F(NTPSnippetsServiceTest, EmptyImageReturnedForNonExistentId) {
944 gfx::Image image;
945 testing::MockFunction<void(const std::string&, const gfx::Image&)>
946 on_image_fetched_mock_function;
947 EXPECT_CALL(on_image_fetched_mock_function,
948 Call(MakeUniqueID(kSnippetUrl2), _))
949 .Times(1)
950 .WillOnce(testing::SaveArg<1>(&image));
951
952 service()->FetchSuggestionImage(
953 MakeUniqueID(kSnippetUrl2),
954 base::Bind(&testing::MockFunction<void(const std::string&,
955 const gfx::Image&)>::Call,
956 base::Unretained(&on_image_fetched_mock_function)));
957
958 base::RunLoop().RunUntilIdle();
959 EXPECT_TRUE(image.IsEmpty());
960 }
961
889 } // namespace ntp_snippets 962 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/ntp_snippets_service.cc ('k') | components/ntp_snippets/pref_names.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698