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

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: rebase. 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
170 // TODO(vitaliii): Remove these convenience functions as they do not provide
171 // that much value and add additional redirections obscuring the code.
119 std::string GetTestJson(const std::vector<std::string>& snippets, 172 std::string GetTestJson(const std::vector<std::string>& snippets,
120 const std::string& category_title) { 173 const std::string& category_title) {
121 return base::StringPrintf( 174 return MultiCategoryJsonBuilder()
122 "{\n" 175 .AddCategoryWithCustomTitle(snippets, /*remote_category_id=*/1,
123 " \"categories\": [{\n" 176 category_title)
124 " \"id\": 1,\n" 177 .Build();
125 " \"localizedTitle\": \"%s\",\n"
126 " \"suggestions\": [%s]\n"
127 " }]\n"
128 "}\n",
129 category_title.c_str(), base::JoinString(snippets, ", ").c_str());
130 } 178 }
131 179
132 std::string GetTestJson(const std::vector<std::string>& snippets) { 180 std::string GetTestJson(const std::vector<std::string>& snippets) {
133 return GetTestJson(snippets, kTestJsonDefaultCategoryTitle); 181 return GetTestJson(snippets, kTestJsonDefaultCategoryTitle);
134 } 182 }
135 183
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) { 184 std::string FormatTime(const base::Time& t) {
160 base::Time::Exploded x; 185 base::Time::Exploded x;
161 t.UTCExplode(&x); 186 t.UTCExplode(&x);
162 return base::StringPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ", x.year, x.month, 187 return base::StringPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ", x.year, x.month,
163 x.day_of_month, x.hour, x.minute, x.second); 188 x.day_of_month, x.hour, x.minute, x.second);
164 } 189 }
165 190
166 std::string GetSnippetWithUrlAndTimesAndSource( 191 std::string GetSnippetWithUrlAndTimesAndSource(
167 const std::vector<std::string>& ids, 192 const std::vector<std::string>& ids,
168 const std::string& url, 193 const std::string& url,
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 class RemoteSuggestionsProviderTest : public ::testing::Test { 419 class RemoteSuggestionsProviderTest : public ::testing::Test {
395 public: 420 public:
396 RemoteSuggestionsProviderTest() 421 RemoteSuggestionsProviderTest()
397 : params_manager_(ntp_snippets::kStudyName, 422 : params_manager_(ntp_snippets::kStudyName,
398 {{"content_suggestions_backend", 423 {{"content_suggestions_backend",
399 kTestContentSuggestionsServerEndpoint}, 424 kTestContentSuggestionsServerEndpoint},
400 {"fetching_personalization", "non_personal"}}), 425 {"fetching_personalization", "non_personal"}}),
401 fake_url_fetcher_factory_( 426 fake_url_fetcher_factory_(
402 /*default_factory=*/&failing_url_fetcher_factory_), 427 /*default_factory=*/&failing_url_fetcher_factory_),
403 test_url_(kTestContentSuggestionsServerWithAPIKey), 428 test_url_(kTestContentSuggestionsServerWithAPIKey),
429 category_ranker_(base::MakeUnique<ConstantCategoryRanker>()),
404 user_classifier_(/*pref_service=*/nullptr), 430 user_classifier_(/*pref_service=*/nullptr),
405 image_fetcher_(nullptr), 431 image_fetcher_(nullptr),
406 image_decoder_(nullptr), 432 image_decoder_(nullptr),
407 database_(nullptr) { 433 database_(nullptr) {
408 RemoteSuggestionsProvider::RegisterProfilePrefs( 434 RemoteSuggestionsProvider::RegisterProfilePrefs(
409 utils_.pref_service()->registry()); 435 utils_.pref_service()->registry());
410 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); 436 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry());
411 437
412 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); 438 EXPECT_TRUE(database_dir_.CreateUniqueTempDir());
413 } 439 }
414 440
415 ~RemoteSuggestionsProviderTest() override { 441 ~RemoteSuggestionsProviderTest() override {
416 // We need to run the message loop after deleting the database, because 442 // We need to run the message loop after deleting the database, because
417 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task 443 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task
418 // runner. Without this, we'd get reports of memory leaks. 444 // runner. Without this, we'd get reports of memory leaks.
419 base::RunLoop().RunUntilIdle(); 445 base::RunLoop().RunUntilIdle();
420 } 446 }
421 447
448 // TODO(vitaliii): Rewrite this function to initialize a test class member
449 // instead of creating a new service.
422 std::unique_ptr<RemoteSuggestionsProvider> MakeSnippetsService( 450 std::unique_ptr<RemoteSuggestionsProvider> MakeSnippetsService(
423 bool set_empty_response = true) { 451 bool set_empty_response = true) {
424 auto service = MakeSnippetsServiceWithoutInitialization(); 452 auto service = MakeSnippetsServiceWithoutInitialization();
425 WaitForSnippetsServiceInitialization(service.get(), set_empty_response); 453 WaitForSnippetsServiceInitialization(service.get(), set_empty_response);
426 return service; 454 return service;
427 } 455 }
428 456
429 std::unique_ptr<RemoteSuggestionsProvider> 457 std::unique_ptr<RemoteSuggestionsProvider>
430 MakeSnippetsServiceWithoutInitialization() { 458 MakeSnippetsServiceWithoutInitialization() {
431 scoped_refptr<base::SingleThreadTaskRunner> task_runner( 459 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
432 base::ThreadTaskRunnerHandle::Get()); 460 base::ThreadTaskRunnerHandle::Get());
433 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = 461 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
434 new net::TestURLRequestContextGetter(task_runner.get()); 462 new net::TestURLRequestContextGetter(task_runner.get());
435 463
436 utils_.ResetSigninManager(); 464 utils_.ResetSigninManager();
437 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher = 465 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher =
438 base::MakeUnique<NTPSnippetsFetcher>( 466 base::MakeUnique<NTPSnippetsFetcher>(
439 utils_.fake_signin_manager(), fake_token_service_.get(), 467 utils_.fake_signin_manager(), fake_token_service_.get(),
440 std::move(request_context_getter), utils_.pref_service(), 468 std::move(request_context_getter), utils_.pref_service(), nullptr,
441 &category_factory_, nullptr, base::Bind(&ParseJson), kAPIKey, 469 base::Bind(&ParseJson), kAPIKey, &user_classifier_);
442 &user_classifier_);
443 470
444 utils_.fake_signin_manager()->SignIn("foo@bar.com"); 471 utils_.fake_signin_manager()->SignIn("foo@bar.com");
445 472
446 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>(); 473 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>();
447 474
448 image_fetcher_ = image_fetcher.get(); 475 image_fetcher_ = image_fetcher.get();
449 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_)); 476 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_));
450 auto image_decoder = base::MakeUnique<FakeImageDecoder>(); 477 auto image_decoder = base::MakeUnique<FakeImageDecoder>();
451 image_decoder_ = image_decoder.get(); 478 image_decoder_ = image_decoder.get();
452 EXPECT_FALSE(observer_); 479 EXPECT_FALSE(observer_);
453 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>(); 480 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>();
454 auto database = base::MakeUnique<RemoteSuggestionsDatabase>( 481 auto database = base::MakeUnique<RemoteSuggestionsDatabase>(
455 database_dir_.GetPath(), task_runner); 482 database_dir_.GetPath(), task_runner);
456 database_ = database.get(); 483 database_ = database.get();
457 return base::MakeUnique<RemoteSuggestionsProvider>( 484 return base::MakeUnique<RemoteSuggestionsProvider>(
458 observer_.get(), &category_factory_, utils_.pref_service(), "fr", 485 observer_.get(), utils_.pref_service(), "fr", category_ranker_.get(),
459 &user_classifier_, &scheduler_, std::move(snippets_fetcher), 486 &user_classifier_, &scheduler_, std::move(snippets_fetcher),
460 std::move(image_fetcher), std::move(image_decoder), 487 std::move(image_fetcher), std::move(image_decoder), std::move(database),
461 std::move(database),
462 base::MakeUnique<RemoteSuggestionsStatusService>( 488 base::MakeUnique<RemoteSuggestionsStatusService>(
463 utils_.fake_signin_manager(), utils_.pref_service())); 489 utils_.fake_signin_manager(), utils_.pref_service()));
464 } 490 }
465 491
466 void WaitForSnippetsServiceInitialization(RemoteSuggestionsProvider* service, 492 void WaitForSnippetsServiceInitialization(RemoteSuggestionsProvider* service,
467 bool set_empty_response) { 493 bool set_empty_response) {
468 EXPECT_EQ(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 494 EXPECT_EQ(RemoteSuggestionsProvider::State::NOT_INITED, service->state_);
469 495
470 // 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
471 // is nothing in the DB. 497 // is nothing in the DB.
472 if (set_empty_response) { 498 if (set_empty_response) {
473 SetUpFetchResponse(GetTestJson(std::vector<std::string>())); 499 SetUpFetchResponse(GetTestJson(std::vector<std::string>()));
474 } 500 }
475 501
476 // 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.
477 base::RunLoop().RunUntilIdle(); 503 base::RunLoop().RunUntilIdle();
478 EXPECT_NE(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 504 EXPECT_NE(RemoteSuggestionsProvider::State::NOT_INITED, service->state_);
479 } 505 }
480 506
481 void ResetSnippetsService( 507 void ResetSnippetsService(std::unique_ptr<RemoteSuggestionsProvider>* service,
482 std::unique_ptr<RemoteSuggestionsProvider>* service) { 508 bool set_empty_response) {
483 service->reset(); 509 service->reset();
484 observer_.reset(); 510 observer_.reset();
485 *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);
486 } 516 }
487 517
488 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) { 518 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) {
489 return ContentSuggestion::ID(articles_category(), id_within_category); 519 return ContentSuggestion::ID(articles_category(), id_within_category);
490 } 520 }
491 521
492 Category articles_category() { 522 Category articles_category() {
493 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES); 523 return Category::FromKnownCategory(KnownCategories::ARTICLES);
494 } 524 }
495 525
496 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) { 526 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) {
497 return ContentSuggestion::ID(other_category(), id_within_category); 527 return ContentSuggestion::ID(other_category(), id_within_category);
498 } 528 }
499 529
500 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); }
501 533
502 Category unknown_category() { 534 Category unknown_category() {
503 return category_factory_.FromRemoteCategory(kUnknownRemoteCategoryId); 535 return Category::FromRemoteCategory(kUnknownRemoteCategoryId);
504 } 536 }
505 537
506 protected: 538 protected:
507 const GURL& test_url() { return test_url_; } 539 const GURL& test_url() { return test_url_; }
508 FakeContentSuggestionsProviderObserver& observer() { return *observer_; } 540 FakeContentSuggestionsProviderObserver& observer() { return *observer_; }
509 MockScheduler& mock_scheduler() { return scheduler_; } 541 MockScheduler& mock_scheduler() { return scheduler_; }
510 // 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
511 // network requests. 543 // network requests.
512 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; } 544 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; }
513 FakeImageDecoder* image_decoder() { return image_decoder_; } 545 FakeImageDecoder* image_decoder() { return image_decoder_; }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 578
547 private: 579 private:
548 variations::testing::VariationParamsManager params_manager_; 580 variations::testing::VariationParamsManager params_manager_;
549 test::RemoteSuggestionsTestUtils utils_; 581 test::RemoteSuggestionsTestUtils utils_;
550 base::MessageLoop message_loop_; 582 base::MessageLoop message_loop_;
551 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; 583 FailingFakeURLFetcherFactory failing_url_fetcher_factory_;
552 // Instantiation of factory automatically sets itself as URLFetcher's factory. 584 // Instantiation of factory automatically sets itself as URLFetcher's factory.
553 net::FakeURLFetcherFactory fake_url_fetcher_factory_; 585 net::FakeURLFetcherFactory fake_url_fetcher_factory_;
554 const GURL test_url_; 586 const GURL test_url_;
555 std::unique_ptr<OAuth2TokenService> fake_token_service_; 587 std::unique_ptr<OAuth2TokenService> fake_token_service_;
588 std::unique_ptr<CategoryRanker> category_ranker_;
556 UserClassifier user_classifier_; 589 UserClassifier user_classifier_;
557 NiceMock<MockScheduler> scheduler_; 590 NiceMock<MockScheduler> scheduler_;
558 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; 591 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_;
559 CategoryFactory category_factory_;
560 NiceMock<MockImageFetcher>* image_fetcher_; 592 NiceMock<MockImageFetcher>* image_fetcher_;
561 FakeImageDecoder* image_decoder_; 593 FakeImageDecoder* image_decoder_;
562 594
563 base::ScopedTempDir database_dir_; 595 base::ScopedTempDir database_dir_;
564 RemoteSuggestionsDatabase* database_; 596 RemoteSuggestionsDatabase* database_;
565 597
566 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderTest); 598 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderTest);
567 }; 599 };
568 600
569 TEST_F(RemoteSuggestionsProviderTest, ScheduleOnStart) { 601 TEST_F(RemoteSuggestionsProviderTest, ScheduleOnStart) {
(...skipping 14 matching lines...) Expand all
584 SetUpFetchResponse(GetTestJson({GetSnippet()})); 616 SetUpFetchResponse(GetTestJson({GetSnippet()}));
585 auto service = MakeSnippetsService(/*set_empty_response=*/false); 617 auto service = MakeSnippetsService(/*set_empty_response=*/false);
586 618
587 // When recreating the service, we should not get any |Schedule| calls: 619 // When recreating the service, we should not get any |Schedule| calls:
588 // The tasks are already scheduled with the correct intervals, so nothing on 620 // The tasks are already scheduled with the correct intervals, so nothing on
589 // initialization, and the service has data from the DB, so no automatic fetch 621 // initialization, and the service has data from the DB, so no automatic fetch
590 // should happen. 622 // should happen.
591 Mock::VerifyAndClearExpectations(&mock_scheduler()); 623 Mock::VerifyAndClearExpectations(&mock_scheduler());
592 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0); 624 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0);
593 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); 625 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
594 ResetSnippetsService(&service); 626 ResetSnippetsService(&service, /*set_empty_response=*/true);
595 } 627 }
596 628
597 TEST_F(RemoteSuggestionsProviderTest, RescheduleAfterSuccessfulFetch) { 629 TEST_F(RemoteSuggestionsProviderTest, RescheduleAfterSuccessfulFetch) {
598 // We should get two |Schedule| calls: The first when initialization 630 // We should get two |Schedule| calls: The first when initialization
599 // completes, the second one after the automatic (since the service doesn't 631 // completes, the second one after the automatic (since the service doesn't
600 // have any data yet) fetch finishes. 632 // have any data yet) fetch finishes.
601 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2); 633 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
602 auto service = MakeSnippetsService(); 634 auto service = MakeSnippetsService();
603 635
604 // A successful fetch should trigger another |Schedule|. 636 // A successful fetch should trigger another |Schedule|.
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category()); 767 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category());
736 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title()))); 768 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title())));
737 EXPECT_THAT(test_default_title, Eq(info_with_title.title())); 769 EXPECT_THAT(test_default_title, Eq(info_with_title.title()));
738 EXPECT_THAT(info_before.has_more_action(), Eq(true)); 770 EXPECT_THAT(info_before.has_more_action(), Eq(true));
739 EXPECT_THAT(info_before.has_reload_action(), Eq(true)); 771 EXPECT_THAT(info_before.has_reload_action(), Eq(true));
740 EXPECT_THAT(info_before.has_view_all_action(), Eq(false)); 772 EXPECT_THAT(info_before.has_view_all_action(), Eq(false));
741 EXPECT_THAT(info_before.show_if_empty(), Eq(true)); 773 EXPECT_THAT(info_before.show_if_empty(), Eq(true));
742 } 774 }
743 775
744 TEST_F(RemoteSuggestionsProviderTest, MultipleCategories) { 776 TEST_F(RemoteSuggestionsProviderTest, MultipleCategories) {
745 std::string json_str(
746 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}));
747
748 auto service = MakeSnippetsService(); 777 auto service = MakeSnippetsService();
749 778 std::string json_str =
779 MultiCategoryJsonBuilder()
780 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
781 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/2)
782 .Build();
750 LoadFromJSONString(service.get(), json_str); 783 LoadFromJSONString(service.get(), json_str);
751 784
752 ASSERT_THAT(observer().statuses(), 785 ASSERT_THAT(observer().statuses(),
753 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{ 786 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{
754 {articles_category(), CategoryStatus::AVAILABLE}, 787 {articles_category(), CategoryStatus::AVAILABLE},
755 {other_category(), CategoryStatus::AVAILABLE}, 788 {other_category(), CategoryStatus::AVAILABLE},
756 })); 789 }));
757 790
758 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 791 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
759 EXPECT_THAT(service->GetSnippetsForTesting(other_category()), SizeIs(1)); 792 EXPECT_THAT(service->GetSnippetsForTesting(other_category()), SizeIs(1));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 auto service = MakeSnippetsService(); 825 auto service = MakeSnippetsService();
793 CategoryInfo article_info = service->GetCategoryInfo(articles_category()); 826 CategoryInfo article_info = service->GetCategoryInfo(articles_category());
794 EXPECT_THAT(article_info.has_more_action(), Eq(true)); 827 EXPECT_THAT(article_info.has_more_action(), Eq(true));
795 EXPECT_THAT(article_info.has_reload_action(), Eq(true)); 828 EXPECT_THAT(article_info.has_reload_action(), Eq(true));
796 EXPECT_THAT(article_info.has_view_all_action(), Eq(false)); 829 EXPECT_THAT(article_info.has_view_all_action(), Eq(false));
797 EXPECT_THAT(article_info.show_if_empty(), Eq(true)); 830 EXPECT_THAT(article_info.show_if_empty(), Eq(true));
798 } 831 }
799 832
800 TEST_F(RemoteSuggestionsProviderTest, ExperimentalCategoryInfo) { 833 TEST_F(RemoteSuggestionsProviderTest, ExperimentalCategoryInfo) {
801 auto service = MakeSnippetsService(); 834 auto service = MakeSnippetsService();
802 835 std::string json_str =
836 MultiCategoryJsonBuilder()
837 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
838 .AddCategory({GetSnippetN(1)}, kUnknownRemoteCategoryId)
839 .Build();
803 // Load data with multiple categories so that a new experimental category gets 840 // Load data with multiple categories so that a new experimental category gets
804 // registered. 841 // registered.
805 LoadFromJSONString(service.get(), 842 LoadFromJSONString(service.get(), json_str);
806 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 843
807 kUnknownRemoteCategoryId));
808 CategoryInfo info = service->GetCategoryInfo(unknown_category()); 844 CategoryInfo info = service->GetCategoryInfo(unknown_category());
809 EXPECT_THAT(info.has_more_action(), Eq(false)); 845 EXPECT_THAT(info.has_more_action(), Eq(false));
810 EXPECT_THAT(info.has_reload_action(), Eq(false)); 846 EXPECT_THAT(info.has_reload_action(), Eq(false));
811 EXPECT_THAT(info.has_view_all_action(), Eq(false)); 847 EXPECT_THAT(info.has_view_all_action(), Eq(false));
812 EXPECT_THAT(info.show_if_empty(), Eq(false)); 848 EXPECT_THAT(info.show_if_empty(), Eq(false));
813 } 849 }
814 850
851 TEST_F(RemoteSuggestionsProviderTest, AddRemoteCategoriesToCategoryRanker) {
852 auto mock_ranker = base::MakeUnique<MockCategoryRanker>();
853 MockCategoryRanker* raw_mock_ranker = mock_ranker.get();
854 SetCategoryRanker(std::move(mock_ranker));
855 std::string json_str =
856 MultiCategoryJsonBuilder()
857 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/11)
858 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/13)
859 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/12)
860 .Build();
861 SetUpFetchResponse(json_str);
862 {
863 // The order of categories is determined by the order in which they are
864 // added. Thus, the latter is tested here.
865 InSequence s;
866 EXPECT_CALL(*raw_mock_ranker,
867 AppendCategoryIfNecessary(Category::FromRemoteCategory(11)));
868 EXPECT_CALL(*raw_mock_ranker,
869 AppendCategoryIfNecessary(Category::FromRemoteCategory(13)));
870 EXPECT_CALL(*raw_mock_ranker,
871 AppendCategoryIfNecessary(Category::FromRemoteCategory(12)));
872 }
873 auto service = MakeSnippetsService(/*set_empty_response=*/false);
874 }
875
815 TEST_F(RemoteSuggestionsProviderTest, PersistCategoryInfos) { 876 TEST_F(RemoteSuggestionsProviderTest, PersistCategoryInfos) {
816 auto service = MakeSnippetsService(); 877 auto service = MakeSnippetsService();
817 878 // TODO(vitaliii): Use |articles_category()| instead of constant ID below.
818 LoadFromJSONString(service.get(), 879 std::string json_str =
819 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 880 MultiCategoryJsonBuilder()
820 kUnknownRemoteCategoryId)); 881 .AddCategoryWithCustomTitle(
882 {GetSnippetN(0)}, /*remote_category_id=*/1, "Articles for You")
883 .AddCategoryWithCustomTitle({GetSnippetN(1)},
884 kUnknownRemoteCategoryId, "Other Things")
885 .Build();
886 LoadFromJSONString(service.get(), json_str);
821 887
822 ASSERT_EQ(observer().StatusForCategory(articles_category()), 888 ASSERT_EQ(observer().StatusForCategory(articles_category()),
823 CategoryStatus::AVAILABLE); 889 CategoryStatus::AVAILABLE);
824 ASSERT_EQ(observer().StatusForCategory(unknown_category()), 890 ASSERT_EQ(observer().StatusForCategory(unknown_category()),
825 CategoryStatus::AVAILABLE); 891 CategoryStatus::AVAILABLE);
826 892
827 CategoryInfo info_articles_before = 893 CategoryInfo info_articles_before =
828 service->GetCategoryInfo(articles_category()); 894 service->GetCategoryInfo(articles_category());
829 CategoryInfo info_unknown_before = 895 CategoryInfo info_unknown_before =
830 service->GetCategoryInfo(unknown_category()); 896 service->GetCategoryInfo(unknown_category());
831 897
832 // Recreate the service to simulate a Chrome restart. 898 // Recreate the service to simulate a Chrome restart.
833 ResetSnippetsService(&service); 899 ResetSnippetsService(&service, /*set_empty_response=*/true);
834 900
835 // The categories should have been restored. 901 // The categories should have been restored.
836 ASSERT_NE(observer().StatusForCategory(articles_category()), 902 ASSERT_NE(observer().StatusForCategory(articles_category()),
837 CategoryStatus::NOT_PROVIDED); 903 CategoryStatus::NOT_PROVIDED);
838 ASSERT_NE(observer().StatusForCategory(unknown_category()), 904 ASSERT_NE(observer().StatusForCategory(unknown_category()),
839 CategoryStatus::NOT_PROVIDED); 905 CategoryStatus::NOT_PROVIDED);
840 906
841 EXPECT_EQ(observer().StatusForCategory(articles_category()), 907 EXPECT_EQ(observer().StatusForCategory(articles_category()),
842 CategoryStatus::AVAILABLE); 908 CategoryStatus::AVAILABLE);
843 EXPECT_EQ(observer().StatusForCategory(unknown_category()), 909 EXPECT_EQ(observer().StatusForCategory(unknown_category()),
844 CategoryStatus::AVAILABLE); 910 CategoryStatus::AVAILABLE);
845 911
846 CategoryInfo info_articles_after = 912 CategoryInfo info_articles_after =
847 service->GetCategoryInfo(articles_category()); 913 service->GetCategoryInfo(articles_category());
848 CategoryInfo info_unknown_after = 914 CategoryInfo info_unknown_after =
849 service->GetCategoryInfo(unknown_category()); 915 service->GetCategoryInfo(unknown_category());
850 916
851 EXPECT_EQ(info_articles_before.title(), info_articles_after.title()); 917 EXPECT_EQ(info_articles_before.title(), info_articles_after.title());
852 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title()); 918 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title());
853 } 919 }
854 920
921 TEST_F(RemoteSuggestionsProviderTest, PersistRemoteCategoryOrder) {
922 // We create a service with a normal ranker to store the order.
923 std::string json_str =
924 MultiCategoryJsonBuilder()
925 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/11)
926 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/13)
927 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/12)
928 .Build();
929 SetUpFetchResponse(json_str);
930 auto service = MakeSnippetsService(/*set_empty_response=*/false);
931
932 // We manually recreate the service to simulate Chrome restart and enforce a
933 // mock ranker. The response is cleared to ensure that the order is not
934 // fetched.
935 SetUpFetchResponse("");
936 auto mock_ranker = base::MakeUnique<MockCategoryRanker>();
937 MockCategoryRanker* raw_mock_ranker = mock_ranker.get();
938 SetCategoryRanker(std::move(mock_ranker));
939 {
940 // The order of categories is determined by the order in which they are
941 // added. Thus, the latter is tested here.
942 InSequence s;
943 // Article category always exists and, therefore, it is stored in prefs too.
944 EXPECT_CALL(*raw_mock_ranker,
945 AppendCategoryIfNecessary(articles_category()));
946
947 EXPECT_CALL(*raw_mock_ranker,
948 AppendCategoryIfNecessary(Category::FromRemoteCategory(11)));
949 EXPECT_CALL(*raw_mock_ranker,
950 AppendCategoryIfNecessary(Category::FromRemoteCategory(13)));
951 EXPECT_CALL(*raw_mock_ranker,
952 AppendCategoryIfNecessary(Category::FromRemoteCategory(12)));
953 }
954 ResetSnippetsService(&service, /*set_empty_response=*/false);
955 }
956
855 TEST_F(RemoteSuggestionsProviderTest, PersistSuggestions) { 957 TEST_F(RemoteSuggestionsProviderTest, PersistSuggestions) {
856 auto service = MakeSnippetsService(); 958 auto service = MakeSnippetsService();
857 959 std::string json_str =
858 LoadFromJSONString(service.get(), 960 MultiCategoryJsonBuilder()
859 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 961 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
962 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/2)
963 .Build();
964 LoadFromJSONString(service.get(), json_str);
860 965
861 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 966 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
862 SizeIs(1)); 967 SizeIs(1));
863 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 968 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
864 969
865 // Recreate the service to simulate a Chrome restart. 970 // Recreate the service to simulate a Chrome restart.
866 ResetSnippetsService(&service); 971 ResetSnippetsService(&service, /*set_empty_response=*/true);
867 972
868 // The suggestions in both categories should have been restored. 973 // The suggestions in both categories should have been restored.
869 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 974 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
870 SizeIs(1)); 975 SizeIs(1));
871 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 976 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
872 } 977 }
873 978
874 TEST_F(RemoteSuggestionsProviderTest, DontNotifyIfNotAvailable) { 979 TEST_F(RemoteSuggestionsProviderTest, DontNotifyIfNotAvailable) {
875 // Get some suggestions into the database. 980 // Get some suggestions into the database.
876 auto service = MakeSnippetsService(); 981 auto service = MakeSnippetsService();
877 LoadFromJSONString(service.get(), 982 std::string json_str =
878 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 983 MultiCategoryJsonBuilder()
984 .AddCategory({GetSnippetN(0)},
985 /*remote_category_id=*/1)
986 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/2)
987 .Build();
988 LoadFromJSONString(service.get(), json_str);
989
879 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 990 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
880 SizeIs(1)); 991 SizeIs(1));
881 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 992 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
882 993
883 service.reset(); 994 service.reset();
884 995
885 // Set the pref that disables remote suggestions. 996 // Set the pref that disables remote suggestions.
886 pref_service()->SetBoolean(prefs::kEnableSnippets, false); 997 pref_service()->SetBoolean(prefs::kEnableSnippets, false);
887 998
888 // Recreate the service to simulate a Chrome start. 999 // Recreate the service to simulate a Chrome start.
889 ResetSnippetsService(&service); 1000 ResetSnippetsService(&service, /*set_empty_response=*/true);
890 1001
891 ASSERT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_)); 1002 ASSERT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_));
892 1003
893 // Now the observer should not have received any suggestions. 1004 // Now the observer should not have received any suggestions.
894 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 1005 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
895 IsEmpty()); 1006 IsEmpty());
896 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty()); 1007 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty());
897 } 1008 }
898 1009
899 TEST_F(RemoteSuggestionsProviderTest, Clear) { 1010 TEST_F(RemoteSuggestionsProviderTest, Clear) {
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1)); 1363 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1));
1253 image = FetchImage(service.get(), MakeArticleID(kSnippetUrl)); 1364 image = FetchImage(service.get(), MakeArticleID(kSnippetUrl));
1254 EXPECT_FALSE(image.IsEmpty()); 1365 EXPECT_FALSE(image.IsEmpty());
1255 EXPECT_EQ(1, image.Width()); 1366 EXPECT_EQ(1, image.Width());
1256 1367
1257 // Make sure that fetching the same snippet again does not re-add it. 1368 // Make sure that fetching the same snippet again does not re-add it.
1258 LoadFromJSONString(service.get(), json_str); 1369 LoadFromJSONString(service.get(), json_str);
1259 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1370 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1260 1371
1261 // The snippet should stay dismissed even after re-creating the service. 1372 // The snippet should stay dismissed even after re-creating the service.
1262 ResetSnippetsService(&service); 1373 ResetSnippetsService(&service, /*set_empty_response=*/true);
1263 LoadFromJSONString(service.get(), json_str); 1374 LoadFromJSONString(service.get(), json_str);
1264 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1375 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1265 1376
1266 // The snippet can be added again after clearing dismissed snippets. 1377 // The snippet can be added again after clearing dismissed snippets.
1267 service->ClearDismissedSuggestionsForDebugging(articles_category()); 1378 service->ClearDismissedSuggestionsForDebugging(articles_category());
1268 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1379 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1269 LoadFromJSONString(service.get(), json_str); 1380 LoadFromJSONString(service.get(), json_str);
1270 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1381 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1271 } 1382 }
1272 1383
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1448 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), 1559 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"),
1449 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), 1560 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1),
1450 base::Bucket(/*min=*/1, /*count=*/3))); 1561 base::Bucket(/*min=*/1, /*count=*/3)));
1451 EXPECT_THAT( 1562 EXPECT_THAT(
1452 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), 1563 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"),
1453 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); 1564 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1)));
1454 1565
1455 // There is only a single, dismissed snippet in the database, so recreating 1566 // There is only a single, dismissed snippet in the database, so recreating
1456 // the service will require us to re-fetch. 1567 // the service will require us to re-fetch.
1457 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); 1568 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4);
1458 ResetSnippetsService(&service); 1569 ResetSnippetsService(&service, /*set_empty_response=*/true);
1459 EXPECT_EQ(observer().StatusForCategory(articles_category()), 1570 EXPECT_EQ(observer().StatusForCategory(articles_category()),
1460 CategoryStatus::AVAILABLE); 1571 CategoryStatus::AVAILABLE);
1461 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 5); 1572 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 5);
1462 EXPECT_THAT( 1573 EXPECT_THAT(
1463 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), 1574 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"),
1464 ElementsAre(base::Bucket(/*min=*/1, /*count=*/2))); 1575 ElementsAre(base::Bucket(/*min=*/1, /*count=*/2)));
1465 1576
1466 // But if there's a non-dismissed snippet in the database, recreating it 1577 // But if there's a non-dismissed snippet in the database, recreating it
1467 // shouldn't trigger a fetch. 1578 // shouldn't trigger a fetch.
1468 LoadFromJSONString( 1579 LoadFromJSONString(
1469 service.get(), 1580 service.get(),
1470 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")})); 1581 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")}));
1471 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1582 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1472 ResetSnippetsService(&service); 1583 ResetSnippetsService(&service, /*set_empty_response=*/true);
1473 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1584 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1474 } 1585 }
1475 1586
1476 TEST_F(RemoteSuggestionsProviderTest, DismissShouldRespectAllKnownUrls) { 1587 TEST_F(RemoteSuggestionsProviderTest, DismissShouldRespectAllKnownUrls) {
1477 auto service = MakeSnippetsService(); 1588 auto service = MakeSnippetsService();
1478 1589
1479 const base::Time creation = GetDefaultCreationTime(); 1590 const base::Time creation = GetDefaultCreationTime();
1480 const base::Time expiry = GetDefaultExpirationTime(); 1591 const base::Time expiry = GetDefaultExpirationTime();
1481 const std::vector<std::string> source_urls = { 1592 const std::vector<std::string> source_urls = {
1482 "http://mashable.com/2016/05/11/stolen", 1593 "http://mashable.com/2016/05/11/stolen",
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl)); 1770 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl));
1660 EXPECT_EQ(1, image.Width()); 1771 EXPECT_EQ(1, image.Width());
1661 EXPECT_FALSE(image.IsEmpty()); 1772 EXPECT_FALSE(image.IsEmpty());
1662 1773
1663 // Send new suggestion which don't include the snippet referencing the image. 1774 // Send new suggestion which don't include the snippet referencing the image.
1664 LoadFromJSONString(service.get(), 1775 LoadFromJSONString(service.get(),
1665 GetTestJson({GetSnippetWithUrl( 1776 GetTestJson({GetSnippetWithUrl(
1666 "http://something.com/pletely/unrelated")})); 1777 "http://something.com/pletely/unrelated")}));
1667 // The image should still be available until a restart happens. 1778 // The image should still be available until a restart happens.
1668 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1779 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1669 ResetSnippetsService(&service); 1780 ResetSnippetsService(&service, /*set_empty_response=*/true);
1670 // After the restart, the image should be garbage collected. 1781 // After the restart, the image should be garbage collected.
1671 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1782 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1672 } 1783 }
1673 1784
1674 TEST_F(RemoteSuggestionsProviderTest, 1785 TEST_F(RemoteSuggestionsProviderTest,
1675 ShouldHandleMoreThanMaxSnippetsInResponse) { 1786 ShouldHandleMoreThanMaxSnippetsInResponse) {
1676 auto service = MakeSnippetsService(); 1787 auto service = MakeSnippetsService();
1677 1788
1678 std::vector<std::string> suggestions; 1789 std::vector<std::string> suggestions;
1679 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) { 1790 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 service->FetchSnippetsInTheBackground(); 1824 service->FetchSnippetsInTheBackground();
1714 base::RunLoop().RunUntilIdle(); 1825 base::RunLoop().RunUntilIdle();
1715 EXPECT_EQ( 1826 EXPECT_EQ(
1716 simple_test_clock_ptr->Now().ToInternalValue(), 1827 simple_test_clock_ptr->Now().ToInternalValue(),
1717 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); 1828 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
1718 // TODO(markusheintz): Add a test that simulates a browser restart once the 1829 // TODO(markusheintz): Add a test that simulates a browser restart once the
1719 // scheduler refactoring is done (crbug.com/672434). 1830 // scheduler refactoring is done (crbug.com/672434).
1720 } 1831 }
1721 1832
1722 } // namespace ntp_snippets 1833 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698