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

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@ nits. 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,
tschumann 2016/12/15 18:23:13 that's nice! can you add a TODO() to get rid of th
vitaliii 2016/12/16 08:15:43 Done.
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 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 class RemoteSuggestionsProviderTest : public ::testing::Test { 417 class RemoteSuggestionsProviderTest : public ::testing::Test {
395 public: 418 public:
396 RemoteSuggestionsProviderTest() 419 RemoteSuggestionsProviderTest()
397 : params_manager_(ntp_snippets::kStudyName, 420 : params_manager_(ntp_snippets::kStudyName,
398 {{"content_suggestions_backend", 421 {{"content_suggestions_backend",
399 kTestContentSuggestionsServerEndpoint}, 422 kTestContentSuggestionsServerEndpoint},
400 {"fetching_personalization", "non_personal"}}), 423 {"fetching_personalization", "non_personal"}}),
401 fake_url_fetcher_factory_( 424 fake_url_fetcher_factory_(
402 /*default_factory=*/&failing_url_fetcher_factory_), 425 /*default_factory=*/&failing_url_fetcher_factory_),
403 test_url_(kTestContentSuggestionsServerWithAPIKey), 426 test_url_(kTestContentSuggestionsServerWithAPIKey),
427 category_ranker_(base::MakeUnique<ConstantCategoryRanker>()),
404 user_classifier_(/*pref_service=*/nullptr), 428 user_classifier_(/*pref_service=*/nullptr),
405 image_fetcher_(nullptr), 429 image_fetcher_(nullptr),
406 image_decoder_(nullptr), 430 image_decoder_(nullptr),
407 database_(nullptr) { 431 database_(nullptr) {
408 RemoteSuggestionsProvider::RegisterProfilePrefs( 432 RemoteSuggestionsProvider::RegisterProfilePrefs(
409 utils_.pref_service()->registry()); 433 utils_.pref_service()->registry());
410 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); 434 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry());
411 435
412 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); 436 EXPECT_TRUE(database_dir_.CreateUniqueTempDir());
413 } 437 }
414 438
415 ~RemoteSuggestionsProviderTest() override { 439 ~RemoteSuggestionsProviderTest() override {
416 // We need to run the message loop after deleting the database, because 440 // We need to run the message loop after deleting the database, because
417 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task 441 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task
418 // runner. Without this, we'd get reports of memory leaks. 442 // runner. Without this, we'd get reports of memory leaks.
419 base::RunLoop().RunUntilIdle(); 443 base::RunLoop().RunUntilIdle();
420 } 444 }
421 445
446 // TODO(vitaliii): Rewrite this function to initialize a test class member
447 // instead of creating a new service.
422 std::unique_ptr<RemoteSuggestionsProvider> MakeSnippetsService( 448 std::unique_ptr<RemoteSuggestionsProvider> MakeSnippetsService(
423 bool set_empty_response = true) { 449 bool set_empty_response = true) {
424 auto service = MakeSnippetsServiceWithoutInitialization(); 450 auto service = MakeSnippetsServiceWithoutInitialization();
425 WaitForSnippetsServiceInitialization(service.get(), set_empty_response); 451 WaitForSnippetsServiceInitialization(service.get(), set_empty_response);
426 return service; 452 return service;
427 } 453 }
428 454
429 std::unique_ptr<RemoteSuggestionsProvider> 455 std::unique_ptr<RemoteSuggestionsProvider>
430 MakeSnippetsServiceWithoutInitialization() { 456 MakeSnippetsServiceWithoutInitialization() {
431 scoped_refptr<base::SingleThreadTaskRunner> task_runner( 457 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
432 base::ThreadTaskRunnerHandle::Get()); 458 base::ThreadTaskRunnerHandle::Get());
433 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = 459 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
434 new net::TestURLRequestContextGetter(task_runner.get()); 460 new net::TestURLRequestContextGetter(task_runner.get());
435 461
436 utils_.ResetSigninManager(); 462 utils_.ResetSigninManager();
437 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher = 463 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher =
438 base::MakeUnique<NTPSnippetsFetcher>( 464 base::MakeUnique<NTPSnippetsFetcher>(
439 utils_.fake_signin_manager(), fake_token_service_.get(), 465 utils_.fake_signin_manager(), fake_token_service_.get(),
440 std::move(request_context_getter), utils_.pref_service(), 466 std::move(request_context_getter), utils_.pref_service(), nullptr,
441 &category_factory_, nullptr, base::Bind(&ParseJson), kAPIKey, 467 base::Bind(&ParseJson), kAPIKey, &user_classifier_);
442 &user_classifier_);
443 468
444 utils_.fake_signin_manager()->SignIn("foo@bar.com"); 469 utils_.fake_signin_manager()->SignIn("foo@bar.com");
445 470
446 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>(); 471 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>();
447 472
448 image_fetcher_ = image_fetcher.get(); 473 image_fetcher_ = image_fetcher.get();
449 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_)); 474 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_));
450 auto image_decoder = base::MakeUnique<FakeImageDecoder>(); 475 auto image_decoder = base::MakeUnique<FakeImageDecoder>();
451 image_decoder_ = image_decoder.get(); 476 image_decoder_ = image_decoder.get();
452 EXPECT_FALSE(observer_); 477 EXPECT_FALSE(observer_);
453 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>(); 478 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>();
454 auto database = base::MakeUnique<RemoteSuggestionsDatabase>( 479 auto database = base::MakeUnique<RemoteSuggestionsDatabase>(
455 database_dir_.GetPath(), task_runner); 480 database_dir_.GetPath(), task_runner);
456 database_ = database.get(); 481 database_ = database.get();
457 return base::MakeUnique<RemoteSuggestionsProvider>( 482 return base::MakeUnique<RemoteSuggestionsProvider>(
458 observer_.get(), &category_factory_, utils_.pref_service(), "fr", 483 observer_.get(), utils_.pref_service(), "fr", category_ranker_.get(),
459 &user_classifier_, &scheduler_, std::move(snippets_fetcher), 484 &user_classifier_, &scheduler_, std::move(snippets_fetcher),
460 std::move(image_fetcher), std::move(image_decoder), 485 std::move(image_fetcher), std::move(image_decoder), std::move(database),
461 std::move(database),
462 base::MakeUnique<RemoteSuggestionsStatusService>( 486 base::MakeUnique<RemoteSuggestionsStatusService>(
463 utils_.fake_signin_manager(), utils_.pref_service())); 487 utils_.fake_signin_manager(), utils_.pref_service()));
464 } 488 }
465 489
466 void WaitForSnippetsServiceInitialization(RemoteSuggestionsProvider* service, 490 void WaitForSnippetsServiceInitialization(RemoteSuggestionsProvider* service,
467 bool set_empty_response) { 491 bool set_empty_response) {
468 EXPECT_EQ(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 492 EXPECT_EQ(RemoteSuggestionsProvider::State::NOT_INITED, service->state_);
469 493
470 // Add an initial fetch response, as the service tries to fetch when there 494 // Add an initial fetch response, as the service tries to fetch when there
471 // is nothing in the DB. 495 // is nothing in the DB.
472 if (set_empty_response) { 496 if (set_empty_response) {
473 SetUpFetchResponse(GetTestJson(std::vector<std::string>())); 497 SetUpFetchResponse(GetTestJson(std::vector<std::string>()));
474 } 498 }
475 499
476 // TODO(treib): Find a better way to wait for initialization to finish. 500 // TODO(treib): Find a better way to wait for initialization to finish.
477 base::RunLoop().RunUntilIdle(); 501 base::RunLoop().RunUntilIdle();
478 EXPECT_NE(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 502 EXPECT_NE(RemoteSuggestionsProvider::State::NOT_INITED, service->state_);
479 } 503 }
480 504
481 void ResetSnippetsService( 505 void ResetSnippetsService(std::unique_ptr<RemoteSuggestionsProvider>* service,
482 std::unique_ptr<RemoteSuggestionsProvider>* service) { 506 bool set_empty_response) {
483 service->reset(); 507 service->reset();
484 observer_.reset(); 508 observer_.reset();
485 *service = MakeSnippetsService(); 509 *service = MakeSnippetsService(set_empty_response);
510 }
511
512 void SetCategoryRanker(std::unique_ptr<CategoryRanker> category_ranker) {
513 category_ranker_ = std::move(category_ranker);
486 } 514 }
487 515
488 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) { 516 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) {
489 return ContentSuggestion::ID(articles_category(), id_within_category); 517 return ContentSuggestion::ID(articles_category(), id_within_category);
490 } 518 }
491 519
492 Category articles_category() { 520 Category articles_category() {
493 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES); 521 return Category::FromKnownCategory(KnownCategories::ARTICLES);
494 } 522 }
495 523
496 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) { 524 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) {
497 return ContentSuggestion::ID(other_category(), id_within_category); 525 return ContentSuggestion::ID(other_category(), id_within_category);
498 } 526 }
499 527
500 Category other_category() { return category_factory_.FromRemoteCategory(2); } 528 // TODO(tschumann): Get rid of the convenience other_category() and
529 // unknown_category() helpers -- tests can just define their own.
530 Category other_category() { return Category::FromRemoteCategory(2); }
501 531
502 Category unknown_category() { 532 Category unknown_category() {
503 return category_factory_.FromRemoteCategory(kUnknownRemoteCategoryId); 533 return Category::FromRemoteCategory(kUnknownRemoteCategoryId);
504 } 534 }
505 535
506 protected: 536 protected:
507 const GURL& test_url() { return test_url_; } 537 const GURL& test_url() { return test_url_; }
508 FakeContentSuggestionsProviderObserver& observer() { return *observer_; } 538 FakeContentSuggestionsProviderObserver& observer() { return *observer_; }
509 MockScheduler& mock_scheduler() { return scheduler_; } 539 MockScheduler& mock_scheduler() { return scheduler_; }
510 // TODO(tschumann): Make this a strict-mock. We want to avoid unneccesary 540 // TODO(tschumann): Make this a strict-mock. We want to avoid unneccesary
511 // network requests. 541 // network requests.
512 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; } 542 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; }
513 FakeImageDecoder* image_decoder() { return image_decoder_; } 543 FakeImageDecoder* image_decoder() { return image_decoder_; }
(...skipping 25 matching lines...) Expand all
539 569
540 private: 570 private:
541 variations::testing::VariationParamsManager params_manager_; 571 variations::testing::VariationParamsManager params_manager_;
542 test::RemoteSuggestionsTestUtils utils_; 572 test::RemoteSuggestionsTestUtils utils_;
543 base::MessageLoop message_loop_; 573 base::MessageLoop message_loop_;
544 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; 574 FailingFakeURLFetcherFactory failing_url_fetcher_factory_;
545 // Instantiation of factory automatically sets itself as URLFetcher's factory. 575 // Instantiation of factory automatically sets itself as URLFetcher's factory.
546 net::FakeURLFetcherFactory fake_url_fetcher_factory_; 576 net::FakeURLFetcherFactory fake_url_fetcher_factory_;
547 const GURL test_url_; 577 const GURL test_url_;
548 std::unique_ptr<OAuth2TokenService> fake_token_service_; 578 std::unique_ptr<OAuth2TokenService> fake_token_service_;
579 std::unique_ptr<CategoryRanker> category_ranker_;
549 UserClassifier user_classifier_; 580 UserClassifier user_classifier_;
550 NiceMock<MockScheduler> scheduler_; 581 NiceMock<MockScheduler> scheduler_;
551 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; 582 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_;
552 CategoryFactory category_factory_;
553 NiceMock<MockImageFetcher>* image_fetcher_; 583 NiceMock<MockImageFetcher>* image_fetcher_;
554 FakeImageDecoder* image_decoder_; 584 FakeImageDecoder* image_decoder_;
555 585
556 base::ScopedTempDir database_dir_; 586 base::ScopedTempDir database_dir_;
557 RemoteSuggestionsDatabase* database_; 587 RemoteSuggestionsDatabase* database_;
558 588
559 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderTest); 589 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderTest);
560 }; 590 };
561 591
562 TEST_F(RemoteSuggestionsProviderTest, ScheduleOnStart) { 592 TEST_F(RemoteSuggestionsProviderTest, ScheduleOnStart) {
(...skipping 14 matching lines...) Expand all
577 SetUpFetchResponse(GetTestJson({GetSnippet()})); 607 SetUpFetchResponse(GetTestJson({GetSnippet()}));
578 auto service = MakeSnippetsService(/*set_empty_response=*/false); 608 auto service = MakeSnippetsService(/*set_empty_response=*/false);
579 609
580 // When recreating the service, we should not get any |Schedule| calls: 610 // When recreating the service, we should not get any |Schedule| calls:
581 // 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
582 // 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
583 // should happen. 613 // should happen.
584 Mock::VerifyAndClearExpectations(&mock_scheduler()); 614 Mock::VerifyAndClearExpectations(&mock_scheduler());
585 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0); 615 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0);
586 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); 616 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
587 ResetSnippetsService(&service); 617 ResetSnippetsService(&service, /*set_empty_response=*/true);
588 } 618 }
589 619
590 TEST_F(RemoteSuggestionsProviderTest, RescheduleAfterSuccessfulFetch) { 620 TEST_F(RemoteSuggestionsProviderTest, RescheduleAfterSuccessfulFetch) {
591 // We should get two |Schedule| calls: The first when initialization 621 // We should get two |Schedule| calls: The first when initialization
592 // 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
593 // have any data yet) fetch finishes. 623 // have any data yet) fetch finishes.
594 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2); 624 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
595 auto service = MakeSnippetsService(); 625 auto service = MakeSnippetsService();
596 626
597 // 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
728 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category()); 758 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category());
729 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title()))); 759 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title())));
730 EXPECT_THAT(test_default_title, Eq(info_with_title.title())); 760 EXPECT_THAT(test_default_title, Eq(info_with_title.title()));
731 EXPECT_THAT(info_before.has_more_action(), Eq(true)); 761 EXPECT_THAT(info_before.has_more_action(), Eq(true));
732 EXPECT_THAT(info_before.has_reload_action(), Eq(true)); 762 EXPECT_THAT(info_before.has_reload_action(), Eq(true));
733 EXPECT_THAT(info_before.has_view_all_action(), Eq(false)); 763 EXPECT_THAT(info_before.has_view_all_action(), Eq(false));
734 EXPECT_THAT(info_before.show_if_empty(), Eq(true)); 764 EXPECT_THAT(info_before.show_if_empty(), Eq(true));
735 } 765 }
736 766
737 TEST_F(RemoteSuggestionsProviderTest, MultipleCategories) { 767 TEST_F(RemoteSuggestionsProviderTest, MultipleCategories) {
738 std::string json_str(
739 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}));
740
741 auto service = MakeSnippetsService(); 768 auto service = MakeSnippetsService();
742 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();
743 LoadFromJSONString(service.get(), json_str); 774 LoadFromJSONString(service.get(), json_str);
744 775
745 ASSERT_THAT(observer().statuses(), 776 ASSERT_THAT(observer().statuses(),
746 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{ 777 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{
747 {articles_category(), CategoryStatus::AVAILABLE}, 778 {articles_category(), CategoryStatus::AVAILABLE},
748 {other_category(), CategoryStatus::AVAILABLE}, 779 {other_category(), CategoryStatus::AVAILABLE},
749 })); 780 }));
750 781
751 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 782 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
752 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
785 auto service = MakeSnippetsService(); 816 auto service = MakeSnippetsService();
786 CategoryInfo article_info = service->GetCategoryInfo(articles_category()); 817 CategoryInfo article_info = service->GetCategoryInfo(articles_category());
787 EXPECT_THAT(article_info.has_more_action(), Eq(true)); 818 EXPECT_THAT(article_info.has_more_action(), Eq(true));
788 EXPECT_THAT(article_info.has_reload_action(), Eq(true)); 819 EXPECT_THAT(article_info.has_reload_action(), Eq(true));
789 EXPECT_THAT(article_info.has_view_all_action(), Eq(false)); 820 EXPECT_THAT(article_info.has_view_all_action(), Eq(false));
790 EXPECT_THAT(article_info.show_if_empty(), Eq(true)); 821 EXPECT_THAT(article_info.show_if_empty(), Eq(true));
791 } 822 }
792 823
793 TEST_F(RemoteSuggestionsProviderTest, ExperimentalCategoryInfo) { 824 TEST_F(RemoteSuggestionsProviderTest, ExperimentalCategoryInfo) {
794 auto service = MakeSnippetsService(); 825 auto service = MakeSnippetsService();
795 826 std::string json_str =
827 MultiCategoryJsonBuilder()
828 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
829 .AddCategory({GetSnippetN(1)}, kUnknownRemoteCategoryId)
830 .Build();
796 // 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
797 // registered. 832 // registered.
798 LoadFromJSONString(service.get(), 833 LoadFromJSONString(service.get(), json_str);
799 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 834
800 kUnknownRemoteCategoryId));
801 CategoryInfo info = service->GetCategoryInfo(unknown_category()); 835 CategoryInfo info = service->GetCategoryInfo(unknown_category());
802 EXPECT_THAT(info.has_more_action(), Eq(false)); 836 EXPECT_THAT(info.has_more_action(), Eq(false));
803 EXPECT_THAT(info.has_reload_action(), Eq(false)); 837 EXPECT_THAT(info.has_reload_action(), Eq(false));
804 EXPECT_THAT(info.has_view_all_action(), Eq(false)); 838 EXPECT_THAT(info.has_view_all_action(), Eq(false));
805 EXPECT_THAT(info.show_if_empty(), Eq(false)); 839 EXPECT_THAT(info.show_if_empty(), Eq(false));
806 } 840 }
807 841
842 TEST_F(RemoteSuggestionsProviderTest, AddRemoteCategoriesToCategoryRanker) {
843 auto mock_ranker = base::MakeUnique<MockCategoryRanker>();
844 MockCategoryRanker* raw_mock_ranker = mock_ranker.get();
845 SetCategoryRanker(std::move(mock_ranker));
846 std::string json_str =
847 MultiCategoryJsonBuilder()
848 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/11)
849 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/13)
850 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/12)
851 .Build();
852 SetUpFetchResponse(json_str);
853 {
854 InSequence s;
tschumann 2016/12/15 18:23:13 please add a comment explaining what you test. ie.
vitaliii 2016/12/16 08:15:43 Done.
855 EXPECT_CALL(*raw_mock_ranker,
856 AppendCategoryIfNecessary(Category::FromRemoteCategory(11)));
857 EXPECT_CALL(*raw_mock_ranker,
858 AppendCategoryIfNecessary(Category::FromRemoteCategory(13)));
859 EXPECT_CALL(*raw_mock_ranker,
860 AppendCategoryIfNecessary(Category::FromRemoteCategory(12)));
861 }
862 auto service = MakeSnippetsService(/*set_empty_response=*/false);
863 }
864
808 TEST_F(RemoteSuggestionsProviderTest, PersistCategoryInfos) { 865 TEST_F(RemoteSuggestionsProviderTest, PersistCategoryInfos) {
809 auto service = MakeSnippetsService(); 866 auto service = MakeSnippetsService();
810 867 // TODO(vitaliii): Use |articles_category()| instead of constant ID below.
811 LoadFromJSONString(service.get(), 868 std::string json_str =
812 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 869 MultiCategoryJsonBuilder()
813 kUnknownRemoteCategoryId)); 870 .AddCategoryWithCustomTitle(
871 {GetSnippetN(0)}, /*remote_category_id=*/1, "Articles for You")
872 .AddCategoryWithCustomTitle({GetSnippetN(1)},
873 kUnknownRemoteCategoryId, "Other Things")
874 .Build();
875 LoadFromJSONString(service.get(), json_str);
814 876
815 ASSERT_EQ(observer().StatusForCategory(articles_category()), 877 ASSERT_EQ(observer().StatusForCategory(articles_category()),
816 CategoryStatus::AVAILABLE); 878 CategoryStatus::AVAILABLE);
817 ASSERT_EQ(observer().StatusForCategory(unknown_category()), 879 ASSERT_EQ(observer().StatusForCategory(unknown_category()),
818 CategoryStatus::AVAILABLE); 880 CategoryStatus::AVAILABLE);
819 881
820 CategoryInfo info_articles_before = 882 CategoryInfo info_articles_before =
821 service->GetCategoryInfo(articles_category()); 883 service->GetCategoryInfo(articles_category());
822 CategoryInfo info_unknown_before = 884 CategoryInfo info_unknown_before =
823 service->GetCategoryInfo(unknown_category()); 885 service->GetCategoryInfo(unknown_category());
824 886
825 // Recreate the service to simulate a Chrome restart. 887 // Recreate the service to simulate a Chrome restart.
826 ResetSnippetsService(&service); 888 ResetSnippetsService(&service, /*set_empty_response=*/true);
827 889
828 // The categories should have been restored. 890 // The categories should have been restored.
829 ASSERT_NE(observer().StatusForCategory(articles_category()), 891 ASSERT_NE(observer().StatusForCategory(articles_category()),
830 CategoryStatus::NOT_PROVIDED); 892 CategoryStatus::NOT_PROVIDED);
831 ASSERT_NE(observer().StatusForCategory(unknown_category()), 893 ASSERT_NE(observer().StatusForCategory(unknown_category()),
832 CategoryStatus::NOT_PROVIDED); 894 CategoryStatus::NOT_PROVIDED);
833 895
834 EXPECT_EQ(observer().StatusForCategory(articles_category()), 896 EXPECT_EQ(observer().StatusForCategory(articles_category()),
835 CategoryStatus::AVAILABLE); 897 CategoryStatus::AVAILABLE);
836 EXPECT_EQ(observer().StatusForCategory(unknown_category()), 898 EXPECT_EQ(observer().StatusForCategory(unknown_category()),
837 CategoryStatus::AVAILABLE); 899 CategoryStatus::AVAILABLE);
838 900
839 CategoryInfo info_articles_after = 901 CategoryInfo info_articles_after =
840 service->GetCategoryInfo(articles_category()); 902 service->GetCategoryInfo(articles_category());
841 CategoryInfo info_unknown_after = 903 CategoryInfo info_unknown_after =
842 service->GetCategoryInfo(unknown_category()); 904 service->GetCategoryInfo(unknown_category());
843 905
844 EXPECT_EQ(info_articles_before.title(), info_articles_after.title()); 906 EXPECT_EQ(info_articles_before.title(), info_articles_after.title());
845 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title()); 907 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title());
846 } 908 }
847 909
910 TEST_F(RemoteSuggestionsProviderTest, PersistRemoteCategoryOrder) {
911 // We create a service with a normal ranker to store the order.
912 std::string json_str =
913 MultiCategoryJsonBuilder()
914 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/11)
915 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/13)
916 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/12)
917 .Build();
918 SetUpFetchResponse(json_str);
919 auto service = MakeSnippetsService(/*set_empty_response=*/false);
920
921 // We manually recreate the service to simulate Chrome restart and enforce a
922 // mock ranker. The response is cleared to ensure that the order is not
923 // fetched.
924 SetUpFetchResponse("");
925 auto mock_ranker = base::MakeUnique<MockCategoryRanker>();
926 MockCategoryRanker* raw_mock_ranker = mock_ranker.get();
927 SetCategoryRanker(std::move(mock_ranker));
928 {
929 InSequence s;
930 // Article category always exists and, therefore, it is stored in prefs too.
931 EXPECT_CALL(*raw_mock_ranker,
932 AppendCategoryIfNecessary(Category::FromRemoteCategory(1)));
tschumann 2016/12/15 18:23:13 do we have a constant we can use for the article c
vitaliii 2016/12/16 08:15:43 Done.
933
934 EXPECT_CALL(*raw_mock_ranker,
935 AppendCategoryIfNecessary(Category::FromRemoteCategory(11)));
936 EXPECT_CALL(*raw_mock_ranker,
937 AppendCategoryIfNecessary(Category::FromRemoteCategory(13)));
938 EXPECT_CALL(*raw_mock_ranker,
939 AppendCategoryIfNecessary(Category::FromRemoteCategory(12)));
940 }
941 ResetSnippetsService(&service, /*set_empty_response=*/false);
942 }
943
848 TEST_F(RemoteSuggestionsProviderTest, PersistSuggestions) { 944 TEST_F(RemoteSuggestionsProviderTest, PersistSuggestions) {
849 auto service = MakeSnippetsService(); 945 auto service = MakeSnippetsService();
850 946 std::string json_str =
851 LoadFromJSONString(service.get(), 947 MultiCategoryJsonBuilder()
852 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 948 .AddCategory({GetSnippetN(0)}, /*remote_category_id=*/1)
949 .AddCategory({GetSnippetN(2)}, /*remote_category_id=*/2)
950 .Build();
951 LoadFromJSONString(service.get(), json_str);
853 952
854 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 953 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
855 SizeIs(1)); 954 SizeIs(1));
856 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 955 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
857 956
858 // Recreate the service to simulate a Chrome restart. 957 // Recreate the service to simulate a Chrome restart.
859 ResetSnippetsService(&service); 958 ResetSnippetsService(&service, /*set_empty_response=*/true);
860 959
861 // The suggestions in both categories should have been restored. 960 // The suggestions in both categories should have been restored.
862 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 961 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
863 SizeIs(1)); 962 SizeIs(1));
864 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 963 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
865 } 964 }
866 965
867 TEST_F(RemoteSuggestionsProviderTest, DontNotifyIfNotAvailable) { 966 TEST_F(RemoteSuggestionsProviderTest, DontNotifyIfNotAvailable) {
868 // Get some suggestions into the database. 967 // Get some suggestions into the database.
869 auto service = MakeSnippetsService(); 968 auto service = MakeSnippetsService();
870 LoadFromJSONString(service.get(), 969 std::string json_str =
871 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 970 MultiCategoryJsonBuilder()
971 .AddCategory({GetSnippetN(0)},
972 /*remote_category_id=*/1)
973 .AddCategory({GetSnippetN(1)}, /*remote_category_id=*/2)
974 .Build();
975 LoadFromJSONString(service.get(), json_str);
976
872 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 977 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
873 SizeIs(1)); 978 SizeIs(1));
874 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 979 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
875 980
876 service.reset(); 981 service.reset();
877 982
878 // Set the pref that disables remote suggestions. 983 // Set the pref that disables remote suggestions.
879 pref_service()->SetBoolean(prefs::kEnableSnippets, false); 984 pref_service()->SetBoolean(prefs::kEnableSnippets, false);
880 985
881 // Recreate the service to simulate a Chrome start. 986 // Recreate the service to simulate a Chrome start.
882 ResetSnippetsService(&service); 987 ResetSnippetsService(&service, /*set_empty_response=*/true);
883 988
884 ASSERT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_)); 989 ASSERT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_));
885 990
886 // Now the observer should not have received any suggestions. 991 // Now the observer should not have received any suggestions.
887 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 992 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
888 IsEmpty()); 993 IsEmpty());
889 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty()); 994 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty());
890 } 995 }
891 996
892 TEST_F(RemoteSuggestionsProviderTest, Clear) { 997 TEST_F(RemoteSuggestionsProviderTest, Clear) {
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1)); 1300 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1));
1196 image = FetchImage(service.get(), MakeArticleID(kSnippetUrl)); 1301 image = FetchImage(service.get(), MakeArticleID(kSnippetUrl));
1197 EXPECT_FALSE(image.IsEmpty()); 1302 EXPECT_FALSE(image.IsEmpty());
1198 EXPECT_EQ(1, image.Width()); 1303 EXPECT_EQ(1, image.Width());
1199 1304
1200 // Make sure that fetching the same snippet again does not re-add it. 1305 // Make sure that fetching the same snippet again does not re-add it.
1201 LoadFromJSONString(service.get(), json_str); 1306 LoadFromJSONString(service.get(), json_str);
1202 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1307 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1203 1308
1204 // The snippet should stay dismissed even after re-creating the service. 1309 // The snippet should stay dismissed even after re-creating the service.
1205 ResetSnippetsService(&service); 1310 ResetSnippetsService(&service, /*set_empty_response=*/true);
1206 LoadFromJSONString(service.get(), json_str); 1311 LoadFromJSONString(service.get(), json_str);
1207 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1312 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1208 1313
1209 // The snippet can be added again after clearing dismissed snippets. 1314 // The snippet can be added again after clearing dismissed snippets.
1210 service->ClearDismissedSuggestionsForDebugging(articles_category()); 1315 service->ClearDismissedSuggestionsForDebugging(articles_category());
1211 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1316 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1212 LoadFromJSONString(service.get(), json_str); 1317 LoadFromJSONString(service.get(), json_str);
1213 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1318 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1214 } 1319 }
1215 1320
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1391 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), 1496 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"),
1392 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), 1497 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1),
1393 base::Bucket(/*min=*/1, /*count=*/3))); 1498 base::Bucket(/*min=*/1, /*count=*/3)));
1394 EXPECT_THAT( 1499 EXPECT_THAT(
1395 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), 1500 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"),
1396 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); 1501 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1)));
1397 1502
1398 // There is only a single, dismissed snippet in the database, so recreating 1503 // There is only a single, dismissed snippet in the database, so recreating
1399 // the service will require us to re-fetch. 1504 // the service will require us to re-fetch.
1400 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); 1505 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4);
1401 ResetSnippetsService(&service); 1506 ResetSnippetsService(&service, /*set_empty_response=*/true);
1402 EXPECT_EQ(observer().StatusForCategory(articles_category()), 1507 EXPECT_EQ(observer().StatusForCategory(articles_category()),
1403 CategoryStatus::AVAILABLE); 1508 CategoryStatus::AVAILABLE);
1404 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 5); 1509 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 5);
1405 EXPECT_THAT( 1510 EXPECT_THAT(
1406 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), 1511 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"),
1407 ElementsAre(base::Bucket(/*min=*/1, /*count=*/2))); 1512 ElementsAre(base::Bucket(/*min=*/1, /*count=*/2)));
1408 1513
1409 // But if there's a non-dismissed snippet in the database, recreating it 1514 // But if there's a non-dismissed snippet in the database, recreating it
1410 // shouldn't trigger a fetch. 1515 // shouldn't trigger a fetch.
1411 LoadFromJSONString( 1516 LoadFromJSONString(
1412 service.get(), 1517 service.get(),
1413 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")})); 1518 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")}));
1414 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1519 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1415 ResetSnippetsService(&service); 1520 ResetSnippetsService(&service, /*set_empty_response=*/true);
1416 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1521 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1417 } 1522 }
1418 1523
1419 TEST_F(RemoteSuggestionsProviderTest, DismissShouldRespectAllKnownUrls) { 1524 TEST_F(RemoteSuggestionsProviderTest, DismissShouldRespectAllKnownUrls) {
1420 auto service = MakeSnippetsService(); 1525 auto service = MakeSnippetsService();
1421 1526
1422 const base::Time creation = GetDefaultCreationTime(); 1527 const base::Time creation = GetDefaultCreationTime();
1423 const base::Time expiry = GetDefaultExpirationTime(); 1528 const base::Time expiry = GetDefaultExpirationTime();
1424 const std::vector<std::string> source_urls = { 1529 const std::vector<std::string> source_urls = {
1425 "http://mashable.com/2016/05/11/stolen", 1530 "http://mashable.com/2016/05/11/stolen",
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl)); 1707 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl));
1603 EXPECT_EQ(1, image.Width()); 1708 EXPECT_EQ(1, image.Width());
1604 EXPECT_FALSE(image.IsEmpty()); 1709 EXPECT_FALSE(image.IsEmpty());
1605 1710
1606 // Send new suggestion which don't include the snippet referencing the image. 1711 // Send new suggestion which don't include the snippet referencing the image.
1607 LoadFromJSONString(service.get(), 1712 LoadFromJSONString(service.get(),
1608 GetTestJson({GetSnippetWithUrl( 1713 GetTestJson({GetSnippetWithUrl(
1609 "http://something.com/pletely/unrelated")})); 1714 "http://something.com/pletely/unrelated")}));
1610 // The image should still be available until a restart happens. 1715 // The image should still be available until a restart happens.
1611 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1716 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1612 ResetSnippetsService(&service); 1717 ResetSnippetsService(&service, /*set_empty_response=*/true);
1613 // After the restart, the image should be garbage collected. 1718 // After the restart, the image should be garbage collected.
1614 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1719 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1615 } 1720 }
1616 1721
1617 TEST_F(RemoteSuggestionsProviderTest, 1722 TEST_F(RemoteSuggestionsProviderTest,
1618 ShouldHandleMoreThanMaxSnippetsInResponse) { 1723 ShouldHandleMoreThanMaxSnippetsInResponse) {
1619 auto service = MakeSnippetsService(); 1724 auto service = MakeSnippetsService();
1620 1725
1621 std::vector<std::string> suggestions; 1726 std::vector<std::string> suggestions;
1622 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) { 1727 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1656 service->FetchSnippetsInTheBackground(); 1761 service->FetchSnippetsInTheBackground();
1657 base::RunLoop().RunUntilIdle(); 1762 base::RunLoop().RunUntilIdle();
1658 EXPECT_EQ( 1763 EXPECT_EQ(
1659 simple_test_clock_ptr->Now().ToInternalValue(), 1764 simple_test_clock_ptr->Now().ToInternalValue(),
1660 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); 1765 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
1661 // TODO(markusheintz): Add a test that simulates a browser restart once the 1766 // TODO(markusheintz): Add a test that simulates a browser restart once the
1662 // scheduler refactoring is done (crbug.com/672434). 1767 // scheduler refactoring is done (crbug.com/672434).
1663 } 1768 }
1664 1769
1665 } // namespace ntp_snippets 1770 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698