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

Side by Side Diff: components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc

Issue 2568033005: [NTP::SectionOrder] Replace CategoryFactory with a category ranker. (Closed)
Patch Set: treib@ and tschumann@ comments. Created 4 years 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/remote/remote_suggestions_provider.h" 5 #include "components/ntp_snippets/remote/remote_suggestions_provider.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
13 #include "base/files/scoped_temp_dir.h" 13 #include "base/files/scoped_temp_dir.h"
14 #include "base/json/json_reader.h" 14 #include "base/json/json_reader.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h" 16 #include "base/memory/ptr_util.h"
17 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
18 #include "base/run_loop.h" 18 #include "base/run_loop.h"
19 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
22 #include "base/test/histogram_tester.h" 22 #include "base/test/histogram_tester.h"
23 #include "base/test/simple_test_clock.h" 23 #include "base/test/simple_test_clock.h"
24 #include "base/threading/thread_task_runner_handle.h" 24 #include "base/threading/thread_task_runner_handle.h"
25 #include "base/time/time.h" 25 #include "base/time/time.h"
26 #include "components/image_fetcher/image_decoder.h" 26 #include "components/image_fetcher/image_decoder.h"
27 #include "components/image_fetcher/image_fetcher.h" 27 #include "components/image_fetcher/image_fetcher.h"
28 #include "components/image_fetcher/image_fetcher_delegate.h" 28 #include "components/image_fetcher/image_fetcher_delegate.h"
29 #include "components/ntp_snippets/category_factory.h" 29 #include "components/ntp_snippets/category.h"
30 #include "components/ntp_snippets/category_info.h" 30 #include "components/ntp_snippets/category_info.h"
31 #include "components/ntp_snippets/category_rankers/category_ranker.h"
32 #include "components/ntp_snippets/category_rankers/constant_category_ranker.h"
33 #include "components/ntp_snippets/category_rankers/mock_category_ranker.h"
31 #include "components/ntp_snippets/ntp_snippets_constants.h" 34 #include "components/ntp_snippets/ntp_snippets_constants.h"
32 #include "components/ntp_snippets/pref_names.h" 35 #include "components/ntp_snippets/pref_names.h"
33 #include "components/ntp_snippets/remote/ntp_snippet.h" 36 #include "components/ntp_snippets/remote/ntp_snippet.h"
34 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h" 37 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h"
35 #include "components/ntp_snippets/remote/ntp_snippets_scheduler.h" 38 #include "components/ntp_snippets/remote/ntp_snippets_scheduler.h"
36 #include "components/ntp_snippets/remote/remote_suggestions_database.h" 39 #include "components/ntp_snippets/remote/remote_suggestions_database.h"
37 #include "components/ntp_snippets/remote/test_utils.h" 40 #include "components/ntp_snippets/remote/test_utils.h"
38 #include "components/ntp_snippets/user_classifier.h" 41 #include "components/ntp_snippets/user_classifier.h"
39 #include "components/prefs/testing_pref_service.h" 42 #include "components/prefs/testing_pref_service.h"
40 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" 43 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
41 #include "components/signin/core/browser/fake_signin_manager.h" 44 #include "components/signin/core/browser/fake_signin_manager.h"
42 #include "components/variations/variations_params_manager.h" 45 #include "components/variations/variations_params_manager.h"
43 #include "net/url_request/test_url_fetcher_factory.h" 46 #include "net/url_request/test_url_fetcher_factory.h"
44 #include "net/url_request/url_request_test_util.h" 47 #include "net/url_request/url_request_test_util.h"
45 #include "testing/gmock/include/gmock/gmock.h" 48 #include "testing/gmock/include/gmock/gmock.h"
46 #include "testing/gtest/include/gtest/gtest.h" 49 #include "testing/gtest/include/gtest/gtest.h"
47 #include "ui/gfx/image/image.h" 50 #include "ui/gfx/image/image.h"
48 #include "ui/gfx/image/image_unittest_util.h" 51 #include "ui/gfx/image/image_unittest_util.h"
49 52
50 using image_fetcher::ImageFetcher; 53 using image_fetcher::ImageFetcher;
51 using image_fetcher::ImageFetcherDelegate; 54 using image_fetcher::ImageFetcherDelegate;
55 using testing::_;
52 using testing::ElementsAre; 56 using testing::ElementsAre;
53 using testing::Eq; 57 using testing::Eq;
54 using testing::InSequence; 58 using testing::InSequence;
55 using testing::Invoke; 59 using testing::Invoke;
56 using testing::IsEmpty; 60 using testing::IsEmpty;
57 using testing::Mock; 61 using testing::Mock;
58 using testing::MockFunction; 62 using testing::MockFunction;
59 using testing::NiceMock; 63 using testing::NiceMock;
60 using testing::Not; 64 using testing::Not;
61 using testing::SaveArg; 65 using testing::SaveArg;
62 using testing::SizeIs; 66 using testing::SizeIs;
63 using testing::StartsWith; 67 using testing::StartsWith;
64 using testing::WithArgs; 68 using testing::WithArgs;
65 using testing::_;
66 69
67 namespace ntp_snippets { 70 namespace ntp_snippets {
68 71
69 namespace { 72 namespace {
70 73
71 MATCHER_P(IdEq, value, "") { 74 MATCHER_P(IdEq, value, "") {
72 return arg->id() == value; 75 return arg->id() == value;
73 } 76 }
74 77
75 MATCHER_P(IdWithinCategoryEq, expected_id, "") { 78 MATCHER_P(IdWithinCategoryEq, expected_id, "") {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 base::Time GetDefaultCreationTime() { 112 base::Time GetDefaultCreationTime() {
110 base::Time out_time; 113 base::Time out_time;
111 EXPECT_TRUE(base::Time::FromUTCExploded(kDefaultCreationTime, &out_time)); 114 EXPECT_TRUE(base::Time::FromUTCExploded(kDefaultCreationTime, &out_time));
112 return out_time; 115 return out_time;
113 } 116 }
114 117
115 base::Time GetDefaultExpirationTime() { 118 base::Time GetDefaultExpirationTime() {
116 return base::Time::Now() + base::TimeDelta::FromHours(1); 119 return base::Time::Now() + base::TimeDelta::FromHours(1);
117 } 120 }
118 121
122 std::string GetCategoryJson(const std::vector<std::string>& snippets,
123 int remote_category_id,
124 const std::string& category_title) {
125 return base::StringPrintf(
126 " {\n"
127 " \"id\": %d,\n"
128 " \"localizedTitle\": \"%s\",\n"
129 " \"suggestions\": [%s]\n"
130 " }\n",
131 remote_category_id, category_title.c_str(),
132 base::JoinString(snippets, ", ").c_str());
133 }
134
135 class MultiCategoryJsonBuilder {
136 public:
137 MultiCategoryJsonBuilder() {}
138
139 MultiCategoryJsonBuilder& AddCategoryWithCustomTitle(
140 const std::vector<std::string>& snippets,
141 int remote_category_id,
142 const std::string& category_title) {
143 category_json.push_back(
144 GetCategoryJson(snippets, remote_category_id, category_title));
145 return *this;
146 }
147
148 MultiCategoryJsonBuilder& AddCategory(
149 const std::vector<std::string>& snippets,
150 int remote_category_id) {
151 return AddCategoryWithCustomTitle(
152 snippets, remote_category_id,
153 "Title" + base::IntToString(remote_category_id));
154 }
155
156 std::string Build() {
157 return base::StringPrintf(
158 "{\n"
159 " \"categories\": [\n"
160 "%s\n"
161 " ]\n"
162 "}\n",
163 base::JoinString(category_json, " ,\n").c_str());
164 }
165
166 private:
167 std::vector<std::string> category_json;
168 };
169
119 std::string GetTestJson(const std::vector<std::string>& snippets, 170 std::string GetTestJson(const std::vector<std::string>& snippets,
120 const std::string& category_title) { 171 const std::string& category_title) {
121 return base::StringPrintf( 172 return MultiCategoryJsonBuilder()
122 "{\n" 173 .AddCategoryWithCustomTitle(snippets, /*remote_category_id=*/1,
123 " \"categories\": [{\n" 174 category_title)
124 " \"id\": 1,\n" 175 .Build();
125 " \"localizedTitle\": \"%s\",\n"
126 " \"suggestions\": [%s]\n"
127 " }]\n"
128 "}\n",
129 category_title.c_str(), base::JoinString(snippets, ", ").c_str());
130 } 176 }
131 177
132 std::string GetTestJson(const std::vector<std::string>& snippets) { 178 std::string GetTestJson(const std::vector<std::string>& snippets) {
133 return GetTestJson(snippets, kTestJsonDefaultCategoryTitle); 179 return GetTestJson(snippets, kTestJsonDefaultCategoryTitle);
134 } 180 }
135 181
136 // TODO(tschumann): Remove the default parameter other_id. It makes the tests
137 // less explicit and hard to read. Also get rid of the convenience
138 // other_category() and unknown_category() helpers -- tests can just define
139 // their own.
140 std::string GetMultiCategoryJson(const std::vector<std::string>& articles,
141 const std::vector<std::string>& others,
142 int other_id = 2) {
143 return base::StringPrintf(
144 "{\n"
145 " \"categories\": [{\n"
146 " \"id\": 1,\n"
147 " \"localizedTitle\": \"Articles for You\",\n"
148 " \"suggestions\": [%s]\n"
149 " }, {\n"
150 " \"id\": %i,\n"
151 " \"localizedTitle\": \"Other Things\",\n"
152 " \"suggestions\": [%s]\n"
153 " }]\n"
154 "}\n",
155 base::JoinString(articles, ", ").c_str(), other_id,
156 base::JoinString(others, ", ").c_str());
157 }
158
159 std::string FormatTime(const base::Time& t) { 182 std::string FormatTime(const base::Time& t) {
160 base::Time::Exploded x; 183 base::Time::Exploded x;
161 t.UTCExplode(&x); 184 t.UTCExplode(&x);
162 return base::StringPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ", x.year, x.month, 185 return base::StringPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ", x.year, x.month,
163 x.day_of_month, x.hour, x.minute, x.second); 186 x.day_of_month, x.hour, x.minute, x.second);
164 } 187 }
165 188
166 std::string GetSnippetWithUrlAndTimesAndSource( 189 std::string GetSnippetWithUrlAndTimesAndSource(
167 const std::vector<std::string>& ids, 190 const std::vector<std::string>& ids,
168 const std::string& url, 191 const std::string& url,
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 const image_fetcher::ImageDecodedCallback& callback) override { 405 const image_fetcher::ImageDecodedCallback& callback) override {
383 callback.Run(decoded_image_); 406 callback.Run(decoded_image_);
384 } 407 }
385 408
386 void SetDecodedImage(const gfx::Image& image) { decoded_image_ = image; } 409 void SetDecodedImage(const gfx::Image& image) { decoded_image_ = image; }
387 410
388 private: 411 private:
389 gfx::Image decoded_image_; 412 gfx::Image decoded_image_;
390 }; 413 };
391 414
415 std::unique_ptr<CategoryRanker> MakeConstantCategoryRanker() {
416 return base::MakeUnique<ConstantCategoryRanker>();
Marc Treib 2016/12/15 16:01:18 No need for a helper function for this; just call
vitaliii 2016/12/15 16:53:50 Done.
417 }
418
392 } // namespace 419 } // namespace
393 420
394 class RemoteSuggestionsProviderTest : public ::testing::Test { 421 class RemoteSuggestionsProviderTest : public ::testing::Test {
395 public: 422 public:
396 RemoteSuggestionsProviderTest() 423 RemoteSuggestionsProviderTest()
397 : params_manager_(ntp_snippets::kStudyName, 424 : params_manager_(ntp_snippets::kStudyName,
398 {{"content_suggestions_backend", 425 {{"content_suggestions_backend",
399 kTestContentSuggestionsServerEndpoint}, 426 kTestContentSuggestionsServerEndpoint},
400 {"fetching_personalization", "non_personal"}}), 427 {"fetching_personalization", "non_personal"}}),
401 fake_url_fetcher_factory_( 428 fake_url_fetcher_factory_(
402 /*default_factory=*/&failing_url_fetcher_factory_), 429 /*default_factory=*/&failing_url_fetcher_factory_),
403 test_url_(kTestContentSuggestionsServerWithAPIKey), 430 test_url_(kTestContentSuggestionsServerWithAPIKey),
431 category_ranker_(MakeConstantCategoryRanker()),
404 user_classifier_(/*pref_service=*/nullptr), 432 user_classifier_(/*pref_service=*/nullptr),
405 image_fetcher_(nullptr), 433 image_fetcher_(nullptr),
406 image_decoder_(nullptr) { 434 image_decoder_(nullptr) {
407 RemoteSuggestionsProvider::RegisterProfilePrefs( 435 RemoteSuggestionsProvider::RegisterProfilePrefs(
408 utils_.pref_service()->registry()); 436 utils_.pref_service()->registry());
409 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); 437 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry());
410 438
411 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); 439 EXPECT_TRUE(database_dir_.CreateUniqueTempDir());
412 } 440 }
413 441
414 ~RemoteSuggestionsProviderTest() override { 442 ~RemoteSuggestionsProviderTest() override {
415 // We need to run the message loop after deleting the database, because 443 // We need to run the message loop after deleting the database, because
416 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task 444 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task
417 // runner. Without this, we'd get reports of memory leaks. 445 // runner. Without this, we'd get reports of memory leaks.
418 base::RunLoop().RunUntilIdle(); 446 base::RunLoop().RunUntilIdle();
419 } 447 }
420 448
449 // TODO(vitaliii): Rewrite this function to initialize a test class member
450 // instead of creating a new service.
421 std::unique_ptr<RemoteSuggestionsProvider> MakeSnippetsService( 451 std::unique_ptr<RemoteSuggestionsProvider> MakeSnippetsService(
422 bool set_empty_response = true) { 452 bool set_empty_response = true) {
423 auto service = MakeSnippetsServiceWithoutInitialization(); 453 auto service = MakeSnippetsServiceWithoutInitialization();
424 WaitForSnippetsServiceInitialization(service.get(), set_empty_response); 454 WaitForSnippetsServiceInitialization(service.get(), set_empty_response);
425 return service; 455 return service;
426 } 456 }
427 457
428 std::unique_ptr<RemoteSuggestionsProvider> 458 std::unique_ptr<RemoteSuggestionsProvider>
429 MakeSnippetsServiceWithoutInitialization() { 459 MakeSnippetsServiceWithoutInitialization() {
430 scoped_refptr<base::SingleThreadTaskRunner> task_runner( 460 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
431 base::ThreadTaskRunnerHandle::Get()); 461 base::ThreadTaskRunnerHandle::Get());
432 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = 462 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
433 new net::TestURLRequestContextGetter(task_runner.get()); 463 new net::TestURLRequestContextGetter(task_runner.get());
434 464
435 utils_.ResetSigninManager(); 465 utils_.ResetSigninManager();
436 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher = 466 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher =
437 base::MakeUnique<NTPSnippetsFetcher>( 467 base::MakeUnique<NTPSnippetsFetcher>(
438 utils_.fake_signin_manager(), fake_token_service_.get(), 468 utils_.fake_signin_manager(), fake_token_service_.get(),
439 std::move(request_context_getter), utils_.pref_service(), 469 std::move(request_context_getter), utils_.pref_service(), nullptr,
440 &category_factory_, nullptr, base::Bind(&ParseJson), kAPIKey, 470 base::Bind(&ParseJson), kAPIKey, &user_classifier_);
441 &user_classifier_);
442 471
443 utils_.fake_signin_manager()->SignIn("foo@bar.com"); 472 utils_.fake_signin_manager()->SignIn("foo@bar.com");
444 473
445 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>(); 474 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>();
446 475
447 image_fetcher_ = image_fetcher.get(); 476 image_fetcher_ = image_fetcher.get();
448 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_)); 477 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_));
449 auto image_decoder = base::MakeUnique<FakeImageDecoder>(); 478 auto image_decoder = base::MakeUnique<FakeImageDecoder>();
450 image_decoder_ = image_decoder.get(); 479 image_decoder_ = image_decoder.get();
451 EXPECT_FALSE(observer_); 480 EXPECT_FALSE(observer_);
452 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>(); 481 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>();
453 return base::MakeUnique<RemoteSuggestionsProvider>( 482 return base::MakeUnique<RemoteSuggestionsProvider>(
454 observer_.get(), &category_factory_, utils_.pref_service(), "fr", 483 observer_.get(), utils_.pref_service(), "fr", category_ranker_.get(),
455 &user_classifier_, &scheduler_, std::move(snippets_fetcher), 484 &user_classifier_, &scheduler_, std::move(snippets_fetcher),
456 std::move(image_fetcher), std::move(image_decoder), 485 std::move(image_fetcher), std::move(image_decoder),
457 base::MakeUnique<RemoteSuggestionsDatabase>(database_dir_.GetPath(), 486 base::MakeUnique<RemoteSuggestionsDatabase>(database_dir_.GetPath(),
458 task_runner), 487 task_runner),
459 base::MakeUnique<RemoteSuggestionsStatusService>( 488 base::MakeUnique<RemoteSuggestionsStatusService>(
460 utils_.fake_signin_manager(), utils_.pref_service())); 489 utils_.fake_signin_manager(), utils_.pref_service()));
461 } 490 }
462 491
463 void WaitForSnippetsServiceInitialization(RemoteSuggestionsProvider* service, 492 void WaitForSnippetsServiceInitialization(RemoteSuggestionsProvider* service,
464 bool set_empty_response) { 493 bool set_empty_response) {
465 EXPECT_EQ(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 494 EXPECT_EQ(RemoteSuggestionsProvider::State::NOT_INITED, service->state_);
466 495
467 // Add an initial fetch response, as the service tries to fetch when there 496 // Add an initial fetch response, as the service tries to fetch when there
468 // is nothing in the DB. 497 // is nothing in the DB.
469 if (set_empty_response) { 498 if (set_empty_response) {
470 SetUpFetchResponse(GetTestJson(std::vector<std::string>())); 499 SetUpFetchResponse(GetTestJson(std::vector<std::string>()));
471 } 500 }
472 501
473 // TODO(treib): Find a better way to wait for initialization to finish. 502 // TODO(treib): Find a better way to wait for initialization to finish.
474 base::RunLoop().RunUntilIdle(); 503 base::RunLoop().RunUntilIdle();
475 EXPECT_NE(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 504 EXPECT_NE(RemoteSuggestionsProvider::State::NOT_INITED, service->state_);
476 } 505 }
477 506
478 void ResetSnippetsService( 507 void ResetSnippetsService(std::unique_ptr<RemoteSuggestionsProvider>* service,
479 std::unique_ptr<RemoteSuggestionsProvider>* service) { 508 bool set_empty_response) {
480 service->reset(); 509 service->reset();
481 observer_.reset(); 510 observer_.reset();
482 *service = MakeSnippetsService(); 511 *service = MakeSnippetsService(set_empty_response);
512 }
513
514 void SetCategoryRanker(std::unique_ptr<CategoryRanker> category_ranker) {
515 category_ranker_ = std::move(category_ranker);
483 } 516 }
484 517
485 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) { 518 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) {
486 return ContentSuggestion::ID(articles_category(), id_within_category); 519 return ContentSuggestion::ID(articles_category(), id_within_category);
487 } 520 }
488 521
489 Category articles_category() { 522 Category articles_category() {
490 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES); 523 return Category::FromKnownCategory(KnownCategories::ARTICLES);
491 } 524 }
492 525
493 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) { 526 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) {
494 return ContentSuggestion::ID(other_category(), id_within_category); 527 return ContentSuggestion::ID(other_category(), id_within_category);
495 } 528 }
496 529
497 Category other_category() { return category_factory_.FromRemoteCategory(2); } 530 // TODO(tschumann): Get rid of the convenience other_category() and
531 // unknown_category() helpers -- tests can just define their own.
532 Category other_category() { return Category::FromRemoteCategory(2); }
498 533
499 Category unknown_category() { 534 Category unknown_category() {
500 return category_factory_.FromRemoteCategory(kUnknownRemoteCategoryId); 535 return Category::FromRemoteCategory(kUnknownRemoteCategoryId);
501 } 536 }
502 537
503 protected: 538 protected:
504 const GURL& test_url() { return test_url_; } 539 const GURL& test_url() { return test_url_; }
505 FakeContentSuggestionsProviderObserver& observer() { return *observer_; } 540 FakeContentSuggestionsProviderObserver& observer() { return *observer_; }
506 MockScheduler& mock_scheduler() { return scheduler_; } 541 MockScheduler& mock_scheduler() { return scheduler_; }
507 // TODO(tschumann): Make this a strict-mock. We want to avoid unneccesary 542 // TODO(tschumann): Make this a strict-mock. We want to avoid unneccesary
508 // network requests. 543 // network requests.
509 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; } 544 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; }
510 FakeImageDecoder* image_decoder() { return image_decoder_; } 545 FakeImageDecoder* image_decoder() { return image_decoder_; }
(...skipping 24 matching lines...) Expand all
535 570
536 private: 571 private:
537 variations::testing::VariationParamsManager params_manager_; 572 variations::testing::VariationParamsManager params_manager_;
538 test::RemoteSuggestionsTestUtils utils_; 573 test::RemoteSuggestionsTestUtils utils_;
539 base::MessageLoop message_loop_; 574 base::MessageLoop message_loop_;
540 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; 575 FailingFakeURLFetcherFactory failing_url_fetcher_factory_;
541 // Instantiation of factory automatically sets itself as URLFetcher's factory. 576 // Instantiation of factory automatically sets itself as URLFetcher's factory.
542 net::FakeURLFetcherFactory fake_url_fetcher_factory_; 577 net::FakeURLFetcherFactory fake_url_fetcher_factory_;
543 const GURL test_url_; 578 const GURL test_url_;
544 std::unique_ptr<OAuth2TokenService> fake_token_service_; 579 std::unique_ptr<OAuth2TokenService> fake_token_service_;
580 std::unique_ptr<CategoryRanker> category_ranker_;
545 UserClassifier user_classifier_; 581 UserClassifier user_classifier_;
546 NiceMock<MockScheduler> scheduler_; 582 NiceMock<MockScheduler> scheduler_;
547 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; 583 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_;
548 CategoryFactory category_factory_;
549 NiceMock<MockImageFetcher>* image_fetcher_; 584 NiceMock<MockImageFetcher>* image_fetcher_;
550 FakeImageDecoder* image_decoder_; 585 FakeImageDecoder* image_decoder_;
551 586
552 base::ScopedTempDir database_dir_; 587 base::ScopedTempDir database_dir_;
553 588
554 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderTest); 589 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderTest);
555 }; 590 };
556 591
557 TEST_F(RemoteSuggestionsProviderTest, ScheduleOnStart) { 592 TEST_F(RemoteSuggestionsProviderTest, ScheduleOnStart) {
558 // We should get two |Schedule| calls: The first when initialization 593 // We should get two |Schedule| calls: The first when initialization
(...skipping 13 matching lines...) Expand all
572 SetUpFetchResponse(GetTestJson({GetSnippet()})); 607 SetUpFetchResponse(GetTestJson({GetSnippet()}));
573 auto service = MakeSnippetsService(/*set_empty_response=*/false); 608 auto service = MakeSnippetsService(/*set_empty_response=*/false);
574 609
575 // When recreating the service, we should not get any |Schedule| calls: 610 // When recreating the service, we should not get any |Schedule| calls:
576 // The tasks are already scheduled with the correct intervals, so nothing on 611 // The tasks are already scheduled with the correct intervals, so nothing on
577 // initialization, and the service has data from the DB, so no automatic fetch 612 // initialization, and the service has data from the DB, so no automatic fetch
578 // should happen. 613 // should happen.
579 Mock::VerifyAndClearExpectations(&mock_scheduler()); 614 Mock::VerifyAndClearExpectations(&mock_scheduler());
580 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0); 615 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0);
581 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); 616 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
582 ResetSnippetsService(&service); 617 ResetSnippetsService(&service, /*set_empty_response=*/true);
583 } 618 }
584 619
585 TEST_F(RemoteSuggestionsProviderTest, RescheduleAfterSuccessfulFetch) { 620 TEST_F(RemoteSuggestionsProviderTest, RescheduleAfterSuccessfulFetch) {
586 // We should get two |Schedule| calls: The first when initialization 621 // We should get two |Schedule| calls: The first when initialization
587 // completes, the second one after the automatic (since the service doesn't 622 // completes, the second one after the automatic (since the service doesn't
588 // have any data yet) fetch finishes. 623 // have any data yet) fetch finishes.
589 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2); 624 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
590 auto service = MakeSnippetsService(); 625 auto service = MakeSnippetsService();
591 626
592 // A successful fetch should trigger another |Schedule|. 627 // A successful fetch should trigger another |Schedule|.
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category()); 758 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category());
724 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title()))); 759 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title())));
725 EXPECT_THAT(test_default_title, Eq(info_with_title.title())); 760 EXPECT_THAT(test_default_title, Eq(info_with_title.title()));
726 EXPECT_THAT(info_before.has_more_action(), Eq(true)); 761 EXPECT_THAT(info_before.has_more_action(), Eq(true));
727 EXPECT_THAT(info_before.has_reload_action(), Eq(true)); 762 EXPECT_THAT(info_before.has_reload_action(), Eq(true));
728 EXPECT_THAT(info_before.has_view_all_action(), Eq(false)); 763 EXPECT_THAT(info_before.has_view_all_action(), Eq(false));
729 EXPECT_THAT(info_before.show_if_empty(), Eq(true)); 764 EXPECT_THAT(info_before.show_if_empty(), Eq(true));
730 } 765 }
731 766
732 TEST_F(RemoteSuggestionsProviderTest, MultipleCategories) { 767 TEST_F(RemoteSuggestionsProviderTest, MultipleCategories) {
733 std::string json_str(
734 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}));
735
736 auto service = MakeSnippetsService(); 768 auto service = MakeSnippetsService();
737 769 std::string json_str =
770 MultiCategoryJsonBuilder()
771 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
772 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/2)
773 .Build();
738 LoadFromJSONString(service.get(), json_str); 774 LoadFromJSONString(service.get(), json_str);
739 775
740 ASSERT_THAT(observer().statuses(), 776 ASSERT_THAT(observer().statuses(),
741 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{ 777 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{
742 {articles_category(), CategoryStatus::AVAILABLE}, 778 {articles_category(), CategoryStatus::AVAILABLE},
743 {other_category(), CategoryStatus::AVAILABLE}, 779 {other_category(), CategoryStatus::AVAILABLE},
744 })); 780 }));
745 781
746 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 782 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
747 EXPECT_THAT(service->GetSnippetsForTesting(other_category()), SizeIs(1)); 783 EXPECT_THAT(service->GetSnippetsForTesting(other_category()), SizeIs(1));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 auto service = MakeSnippetsService(); 816 auto service = MakeSnippetsService();
781 CategoryInfo article_info = service->GetCategoryInfo(articles_category()); 817 CategoryInfo article_info = service->GetCategoryInfo(articles_category());
782 EXPECT_THAT(article_info.has_more_action(), Eq(true)); 818 EXPECT_THAT(article_info.has_more_action(), Eq(true));
783 EXPECT_THAT(article_info.has_reload_action(), Eq(true)); 819 EXPECT_THAT(article_info.has_reload_action(), Eq(true));
784 EXPECT_THAT(article_info.has_view_all_action(), Eq(false)); 820 EXPECT_THAT(article_info.has_view_all_action(), Eq(false));
785 EXPECT_THAT(article_info.show_if_empty(), Eq(true)); 821 EXPECT_THAT(article_info.show_if_empty(), Eq(true));
786 } 822 }
787 823
788 TEST_F(RemoteSuggestionsProviderTest, ExperimentalCategoryInfo) { 824 TEST_F(RemoteSuggestionsProviderTest, ExperimentalCategoryInfo) {
789 auto service = MakeSnippetsService(); 825 auto service = MakeSnippetsService();
790 826 std::string json_str =
827 MultiCategoryJsonBuilder()
828 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
829 .AddCategory({GetSnippetN(1)}, kUnknownRemoteCategoryId)
830 .Build();
791 // Load data with multiple categories so that a new experimental category gets 831 // Load data with multiple categories so that a new experimental category gets
792 // registered. 832 // registered.
793 LoadFromJSONString(service.get(), 833 LoadFromJSONString(service.get(), json_str);
794 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 834
795 kUnknownRemoteCategoryId));
796 CategoryInfo info = service->GetCategoryInfo(unknown_category()); 835 CategoryInfo info = service->GetCategoryInfo(unknown_category());
797 EXPECT_THAT(info.has_more_action(), Eq(false)); 836 EXPECT_THAT(info.has_more_action(), Eq(false));
798 EXPECT_THAT(info.has_reload_action(), Eq(false)); 837 EXPECT_THAT(info.has_reload_action(), Eq(false));
799 EXPECT_THAT(info.has_view_all_action(), Eq(false)); 838 EXPECT_THAT(info.has_view_all_action(), Eq(false));
800 EXPECT_THAT(info.show_if_empty(), Eq(false)); 839 EXPECT_THAT(info.show_if_empty(), Eq(false));
801 } 840 }
802 841
842 TEST_F(RemoteSuggestionsProviderTest, AddRemoteCategoriesToCategoryRanker) {
843 auto mock_ranker = new MockCategoryRanker();
844 SetCategoryRanker(std::unique_ptr<CategoryRanker>(mock_ranker));
Marc Treib 2016/12/15 16:01:18 This is a bit yucky, ownership-wise. How about: au
vitaliii 2016/12/15 16:53:50 Done.
845 std::string json_str =
846 MultiCategoryJsonBuilder()
847 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/11)
848 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/13)
849 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/12)
850 .Build();
851 SetUpFetchResponse(json_str);
852 {
853 InSequence s;
854 EXPECT_CALL(*mock_ranker,
855 AppendCategoryIfNecessary(Category::FromRemoteCategory(11)));
856 EXPECT_CALL(*mock_ranker,
857 AppendCategoryIfNecessary(Category::FromRemoteCategory(13)));
858 EXPECT_CALL(*mock_ranker,
859 AppendCategoryIfNecessary(Category::FromRemoteCategory(12)));
860 }
861 auto service = MakeSnippetsService(/*set_empty_response=*/false);
862 }
863
803 TEST_F(RemoteSuggestionsProviderTest, PersistCategoryInfos) { 864 TEST_F(RemoteSuggestionsProviderTest, PersistCategoryInfos) {
804 auto service = MakeSnippetsService(); 865 auto service = MakeSnippetsService();
805 866 // TODO(vitaliii): Use |articles_category()| instead of constant ID below.
806 LoadFromJSONString(service.get(), 867 std::string json_str =
807 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 868 MultiCategoryJsonBuilder()
808 kUnknownRemoteCategoryId)); 869 .AddCategoryWithCustomTitle(
870 {GetSnippetN(0)}, /*remote_category_id=*/1, "Articles for You")
871 .AddCategoryWithCustomTitle({GetSnippetN(1)},
872 kUnknownRemoteCategoryId, "Other Things")
873 .Build();
874 LoadFromJSONString(service.get(), json_str);
809 875
810 ASSERT_EQ(observer().StatusForCategory(articles_category()), 876 ASSERT_EQ(observer().StatusForCategory(articles_category()),
811 CategoryStatus::AVAILABLE); 877 CategoryStatus::AVAILABLE);
812 ASSERT_EQ(observer().StatusForCategory(unknown_category()), 878 ASSERT_EQ(observer().StatusForCategory(unknown_category()),
813 CategoryStatus::AVAILABLE); 879 CategoryStatus::AVAILABLE);
814 880
815 CategoryInfo info_articles_before = 881 CategoryInfo info_articles_before =
816 service->GetCategoryInfo(articles_category()); 882 service->GetCategoryInfo(articles_category());
817 CategoryInfo info_unknown_before = 883 CategoryInfo info_unknown_before =
818 service->GetCategoryInfo(unknown_category()); 884 service->GetCategoryInfo(unknown_category());
819 885
820 // Recreate the service to simulate a Chrome restart. 886 // Recreate the service to simulate a Chrome restart.
821 ResetSnippetsService(&service); 887 ResetSnippetsService(&service, /*set_empty_response=*/true);
822 888
823 // The categories should have been restored. 889 // The categories should have been restored.
824 ASSERT_NE(observer().StatusForCategory(articles_category()), 890 ASSERT_NE(observer().StatusForCategory(articles_category()),
825 CategoryStatus::NOT_PROVIDED); 891 CategoryStatus::NOT_PROVIDED);
826 ASSERT_NE(observer().StatusForCategory(unknown_category()), 892 ASSERT_NE(observer().StatusForCategory(unknown_category()),
827 CategoryStatus::NOT_PROVIDED); 893 CategoryStatus::NOT_PROVIDED);
828 894
829 EXPECT_EQ(observer().StatusForCategory(articles_category()), 895 EXPECT_EQ(observer().StatusForCategory(articles_category()),
830 CategoryStatus::AVAILABLE); 896 CategoryStatus::AVAILABLE);
831 EXPECT_EQ(observer().StatusForCategory(unknown_category()), 897 EXPECT_EQ(observer().StatusForCategory(unknown_category()),
832 CategoryStatus::AVAILABLE); 898 CategoryStatus::AVAILABLE);
833 899
834 CategoryInfo info_articles_after = 900 CategoryInfo info_articles_after =
835 service->GetCategoryInfo(articles_category()); 901 service->GetCategoryInfo(articles_category());
836 CategoryInfo info_unknown_after = 902 CategoryInfo info_unknown_after =
837 service->GetCategoryInfo(unknown_category()); 903 service->GetCategoryInfo(unknown_category());
838 904
839 EXPECT_EQ(info_articles_before.title(), info_articles_after.title()); 905 EXPECT_EQ(info_articles_before.title(), info_articles_after.title());
840 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title()); 906 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title());
841 } 907 }
842 908
909 TEST_F(RemoteSuggestionsProviderTest, PersistRemoteCategoryOrder) {
910 // We create a service with a normal ranker to store the order.
911 std::string json_str =
912 MultiCategoryJsonBuilder()
913 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/11)
914 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/13)
915 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/12)
916 .Build();
917 SetUpFetchResponse(json_str);
918 auto service = MakeSnippetsService(/*set_empty_response=*/false);
919
920 // We manually recreate the service to simulate Chrome restart and enforce a
921 // mock ranker. The response is cleared to ensure that the order is not
922 // fetched.
923 SetUpFetchResponse("");
924 auto mock_ranker = new MockCategoryRanker();
Marc Treib 2016/12/15 16:01:18 Same here.
vitaliii 2016/12/15 16:53:50 Done.
925 SetCategoryRanker(std::unique_ptr<CategoryRanker>(mock_ranker));
926 {
927 InSequence s;
928 // Article category always exists and, therefore, it is stored in prefs too.
929 EXPECT_CALL(*mock_ranker,
930 AppendCategoryIfNecessary(Category::FromRemoteCategory(1)));
931
932 EXPECT_CALL(*mock_ranker,
933 AppendCategoryIfNecessary(Category::FromRemoteCategory(11)));
934 EXPECT_CALL(*mock_ranker,
935 AppendCategoryIfNecessary(Category::FromRemoteCategory(13)));
936 EXPECT_CALL(*mock_ranker,
937 AppendCategoryIfNecessary(Category::FromRemoteCategory(12)));
938 }
939 ResetSnippetsService(&service, /*set_empty_response=*/false);
940 }
941
843 TEST_F(RemoteSuggestionsProviderTest, PersistSuggestions) { 942 TEST_F(RemoteSuggestionsProviderTest, PersistSuggestions) {
844 auto service = MakeSnippetsService(); 943 auto service = MakeSnippetsService();
845 944 std::string json_str =
846 LoadFromJSONString(service.get(), 945 MultiCategoryJsonBuilder()
847 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 946 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
947 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/2)
948 .Build();
949 LoadFromJSONString(service.get(), json_str);
848 950
849 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 951 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
850 SizeIs(1)); 952 SizeIs(1));
851 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 953 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
852 954
853 // Recreate the service to simulate a Chrome restart. 955 // Recreate the service to simulate a Chrome restart.
854 ResetSnippetsService(&service); 956 ResetSnippetsService(&service, /*set_empty_response=*/true);
855 957
856 // The suggestions in both categories should have been restored. 958 // The suggestions in both categories should have been restored.
857 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 959 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
858 SizeIs(1)); 960 SizeIs(1));
859 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 961 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
860 } 962 }
861 963
862 TEST_F(RemoteSuggestionsProviderTest, DontNotifyIfNotAvailable) { 964 TEST_F(RemoteSuggestionsProviderTest, DontNotifyIfNotAvailable) {
863 // Get some suggestions into the database. 965 // Get some suggestions into the database.
864 auto service = MakeSnippetsService(); 966 auto service = MakeSnippetsService();
865 LoadFromJSONString(service.get(), 967 std::string json_str =
866 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 968 MultiCategoryJsonBuilder()
969 .AddCategory({GetSnippetN(0)},
970 /*remote_category_id=*/1)
971 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/2)
972 .Build();
973 LoadFromJSONString(service.get(), json_str);
974
867 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 975 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
868 SizeIs(1)); 976 SizeIs(1));
869 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 977 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
870 978
871 service.reset(); 979 service.reset();
872 980
873 // Set the pref that disables remote suggestions. 981 // Set the pref that disables remote suggestions.
874 pref_service()->SetBoolean(prefs::kEnableSnippets, false); 982 pref_service()->SetBoolean(prefs::kEnableSnippets, false);
875 983
876 // Recreate the service to simulate a Chrome start. 984 // Recreate the service to simulate a Chrome start.
877 ResetSnippetsService(&service); 985 ResetSnippetsService(&service, /*set_empty_response=*/true);
878 986
879 ASSERT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_)); 987 ASSERT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_));
880 988
881 // Now the observer should not have received any suggestions. 989 // Now the observer should not have received any suggestions.
882 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 990 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
883 IsEmpty()); 991 IsEmpty());
884 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty()); 992 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty());
885 } 993 }
886 994
887 TEST_F(RemoteSuggestionsProviderTest, Clear) { 995 TEST_F(RemoteSuggestionsProviderTest, Clear) {
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1)); 1296 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1));
1189 image = FetchImage(service.get(), MakeArticleID(kSnippetUrl)); 1297 image = FetchImage(service.get(), MakeArticleID(kSnippetUrl));
1190 EXPECT_FALSE(image.IsEmpty()); 1298 EXPECT_FALSE(image.IsEmpty());
1191 EXPECT_EQ(1, image.Width()); 1299 EXPECT_EQ(1, image.Width());
1192 1300
1193 // Make sure that fetching the same snippet again does not re-add it. 1301 // Make sure that fetching the same snippet again does not re-add it.
1194 LoadFromJSONString(service.get(), json_str); 1302 LoadFromJSONString(service.get(), json_str);
1195 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1303 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1196 1304
1197 // The snippet should stay dismissed even after re-creating the service. 1305 // The snippet should stay dismissed even after re-creating the service.
1198 ResetSnippetsService(&service); 1306 ResetSnippetsService(&service, /*set_empty_response=*/true);
1199 LoadFromJSONString(service.get(), json_str); 1307 LoadFromJSONString(service.get(), json_str);
1200 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1308 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1201 1309
1202 // The snippet can be added again after clearing dismissed snippets. 1310 // The snippet can be added again after clearing dismissed snippets.
1203 service->ClearDismissedSuggestionsForDebugging(articles_category()); 1311 service->ClearDismissedSuggestionsForDebugging(articles_category());
1204 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1312 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1205 LoadFromJSONString(service.get(), json_str); 1313 LoadFromJSONString(service.get(), json_str);
1206 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1314 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1207 } 1315 }
1208 1316
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1383 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), 1491 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"),
1384 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), 1492 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1),
1385 base::Bucket(/*min=*/1, /*count=*/3))); 1493 base::Bucket(/*min=*/1, /*count=*/3)));
1386 EXPECT_THAT( 1494 EXPECT_THAT(
1387 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), 1495 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"),
1388 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); 1496 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1)));
1389 1497
1390 // There is only a single, dismissed snippet in the database, so recreating 1498 // There is only a single, dismissed snippet in the database, so recreating
1391 // the service will require us to re-fetch. 1499 // the service will require us to re-fetch.
1392 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); 1500 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4);
1393 ResetSnippetsService(&service); 1501 ResetSnippetsService(&service, /*set_empty_response=*/true);
1394 EXPECT_EQ(observer().StatusForCategory(articles_category()), 1502 EXPECT_EQ(observer().StatusForCategory(articles_category()),
1395 CategoryStatus::AVAILABLE); 1503 CategoryStatus::AVAILABLE);
1396 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 5); 1504 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 5);
1397 EXPECT_THAT( 1505 EXPECT_THAT(
1398 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), 1506 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"),
1399 ElementsAre(base::Bucket(/*min=*/1, /*count=*/2))); 1507 ElementsAre(base::Bucket(/*min=*/1, /*count=*/2)));
1400 1508
1401 // But if there's a non-dismissed snippet in the database, recreating it 1509 // But if there's a non-dismissed snippet in the database, recreating it
1402 // shouldn't trigger a fetch. 1510 // shouldn't trigger a fetch.
1403 LoadFromJSONString( 1511 LoadFromJSONString(
1404 service.get(), 1512 service.get(),
1405 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")})); 1513 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")}));
1406 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1514 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1407 ResetSnippetsService(&service); 1515 ResetSnippetsService(&service, /*set_empty_response=*/true);
1408 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1516 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1409 } 1517 }
1410 1518
1411 TEST_F(RemoteSuggestionsProviderTest, DismissShouldRespectAllKnownUrls) { 1519 TEST_F(RemoteSuggestionsProviderTest, DismissShouldRespectAllKnownUrls) {
1412 auto service = MakeSnippetsService(); 1520 auto service = MakeSnippetsService();
1413 1521
1414 const base::Time creation = GetDefaultCreationTime(); 1522 const base::Time creation = GetDefaultCreationTime();
1415 const base::Time expiry = GetDefaultExpirationTime(); 1523 const base::Time expiry = GetDefaultExpirationTime();
1416 const std::vector<std::string> source_urls = { 1524 const std::vector<std::string> source_urls = {
1417 "http://mashable.com/2016/05/11/stolen", 1525 "http://mashable.com/2016/05/11/stolen",
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1566 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl)); 1674 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl));
1567 EXPECT_EQ(1, image.Width()); 1675 EXPECT_EQ(1, image.Width());
1568 EXPECT_FALSE(image.IsEmpty()); 1676 EXPECT_FALSE(image.IsEmpty());
1569 1677
1570 // Send new suggestion which don't include the snippet referencing the image. 1678 // Send new suggestion which don't include the snippet referencing the image.
1571 LoadFromJSONString(service.get(), 1679 LoadFromJSONString(service.get(),
1572 GetTestJson({GetSnippetWithUrl( 1680 GetTestJson({GetSnippetWithUrl(
1573 "http://something.com/pletely/unrelated")})); 1681 "http://something.com/pletely/unrelated")}));
1574 // The image should still be available until a restart happens. 1682 // The image should still be available until a restart happens.
1575 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1683 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1576 ResetSnippetsService(&service); 1684 ResetSnippetsService(&service, /*set_empty_response=*/true);
1577 // After the restart, the image should be garbage collected. 1685 // After the restart, the image should be garbage collected.
1578 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1686 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1579 } 1687 }
1580 1688
1581 TEST_F(RemoteSuggestionsProviderTest, 1689 TEST_F(RemoteSuggestionsProviderTest,
1582 ShouldHandleMoreThanMaxSnippetsInResponse) { 1690 ShouldHandleMoreThanMaxSnippetsInResponse) {
1583 auto service = MakeSnippetsService(); 1691 auto service = MakeSnippetsService();
1584 1692
1585 std::vector<std::string> suggestions; 1693 std::vector<std::string> suggestions;
1586 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) { 1694 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1620 service->FetchSnippetsInTheBackground(); 1728 service->FetchSnippetsInTheBackground();
1621 base::RunLoop().RunUntilIdle(); 1729 base::RunLoop().RunUntilIdle();
1622 EXPECT_EQ( 1730 EXPECT_EQ(
1623 simple_test_clock_ptr->Now().ToInternalValue(), 1731 simple_test_clock_ptr->Now().ToInternalValue(),
1624 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); 1732 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
1625 // TODO(markusheintz): Add a test that simulates a browser restart once the 1733 // TODO(markusheintz): Add a test that simulates a browser restart once the
1626 // scheduler refactoring is done (crbug.com/672434). 1734 // scheduler refactoring is done (crbug.com/672434).
1627 } 1735 }
1628 1736
1629 } // namespace ntp_snippets 1737 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698