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

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

Issue 2557363002: [NTP Snippets] Refactor background scheduling for remote suggestions (Closed)
Patch Set: Tim's comments and splitting RemoteSuggestionsProvider and RemoteSuggestionsProviderImpl 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_impl.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_factory.h"
30 #include "components/ntp_snippets/category_info.h" 30 #include "components/ntp_snippets/category_info.h"
31 #include "components/ntp_snippets/ntp_snippets_constants.h" 31 #include "components/ntp_snippets/ntp_snippets_constants.h"
32 #include "components/ntp_snippets/pref_names.h" 32 #include "components/ntp_snippets/pref_names.h"
33 #include "components/ntp_snippets/remote/ntp_snippet.h" 33 #include "components/ntp_snippets/remote/ntp_snippet.h"
34 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h" 34 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h"
35 #include "components/ntp_snippets/remote/ntp_snippets_scheduler.h" 35 #include "components/ntp_snippets/remote/persistent_scheduler.h"
36 #include "components/ntp_snippets/remote/remote_suggestions_database.h" 36 #include "components/ntp_snippets/remote/remote_suggestions_database.h"
37 #include "components/ntp_snippets/remote/test_utils.h" 37 #include "components/ntp_snippets/remote/test_utils.h"
38 #include "components/ntp_snippets/user_classifier.h" 38 #include "components/ntp_snippets/user_classifier.h"
39 #include "components/prefs/testing_pref_service.h" 39 #include "components/prefs/testing_pref_service.h"
40 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" 40 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
41 #include "components/signin/core/browser/fake_signin_manager.h" 41 #include "components/signin/core/browser/fake_signin_manager.h"
42 #include "components/variations/variations_params_manager.h" 42 #include "components/variations/variations_params_manager.h"
43 #include "net/url_request/test_url_fetcher_factory.h" 43 #include "net/url_request/test_url_fetcher_factory.h"
44 #include "net/url_request/url_request_test_util.h" 44 #include "net/url_request/url_request_test_util.h"
45 #include "testing/gmock/include/gmock/gmock.h" 45 #include "testing/gmock/include/gmock/gmock.h"
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 257
258 void ServeOneByOneImage( 258 void ServeOneByOneImage(
259 image_fetcher::ImageFetcherDelegate* notify, 259 image_fetcher::ImageFetcherDelegate* notify,
260 const std::string& id, 260 const std::string& id,
261 base::Callback<void(const std::string&, const gfx::Image&)> callback) { 261 base::Callback<void(const std::string&, const gfx::Image&)> callback) {
262 base::ThreadTaskRunnerHandle::Get()->PostTask( 262 base::ThreadTaskRunnerHandle::Get()->PostTask(
263 FROM_HERE, base::Bind(callback, id, gfx::test::CreateImage(1, 1))); 263 FROM_HERE, base::Bind(callback, id, gfx::test::CreateImage(1, 1)));
264 notify->OnImageDataFetched(id, "1-by-1-image-data"); 264 notify->OnImageDataFetched(id, "1-by-1-image-data");
265 } 265 }
266 266
267 gfx::Image FetchImage(RemoteSuggestionsProvider* service, 267 gfx::Image FetchImage(RemoteSuggestionsProviderImpl* service,
268 const ContentSuggestion::ID& suggestion_id) { 268 const ContentSuggestion::ID& suggestion_id) {
269 gfx::Image result; 269 gfx::Image result;
270 base::RunLoop run_loop; 270 base::RunLoop run_loop;
271 service->FetchSuggestionImage(suggestion_id, 271 service->FetchSuggestionImage(suggestion_id,
272 base::Bind( 272 base::Bind(
273 [](base::Closure signal, gfx::Image* output, 273 [](base::Closure signal, gfx::Image* output,
274 const gfx::Image& loaded) { 274 const gfx::Image& loaded) {
275 *output = loaded; 275 *output = loaded;
276 signal.Run(); 276 signal.Run();
277 }, 277 },
(...skipping 22 matching lines...) Expand all
300 int id, 300 int id,
301 const GURL& url, 301 const GURL& url,
302 net::URLFetcher::RequestType request_type, 302 net::URLFetcher::RequestType request_type,
303 net::URLFetcherDelegate* d) override { 303 net::URLFetcherDelegate* d) override {
304 return base::MakeUnique<net::FakeURLFetcher>( 304 return base::MakeUnique<net::FakeURLFetcher>(
305 url, d, /*response_data=*/std::string(), net::HTTP_NOT_FOUND, 305 url, d, /*response_data=*/std::string(), net::HTTP_NOT_FOUND,
306 net::URLRequestStatus::FAILED); 306 net::URLRequestStatus::FAILED);
307 } 307 }
308 }; 308 };
309 309
310 class MockScheduler : public NTPSnippetsScheduler {
311 public:
312 MOCK_METHOD2(Schedule,
313 bool(base::TimeDelta period_wifi,
314 base::TimeDelta period_fallback));
315 MOCK_METHOD0(Unschedule, bool());
316 };
317
318 class MockImageFetcher : public ImageFetcher { 310 class MockImageFetcher : public ImageFetcher {
319 public: 311 public:
320 MOCK_METHOD1(SetImageFetcherDelegate, void(ImageFetcherDelegate*)); 312 MOCK_METHOD1(SetImageFetcherDelegate, void(ImageFetcherDelegate*));
321 MOCK_METHOD1(SetDataUseServiceName, void(DataUseServiceName)); 313 MOCK_METHOD1(SetDataUseServiceName, void(DataUseServiceName));
322 MOCK_METHOD3( 314 MOCK_METHOD3(
323 StartOrQueueNetworkRequest, 315 StartOrQueueNetworkRequest,
324 void(const std::string&, 316 void(const std::string&,
325 const GURL&, 317 const GURL&,
326 base::Callback<void(const std::string&, const gfx::Image&)>)); 318 base::Callback<void(const std::string&, const gfx::Image&)>));
327 }; 319 };
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 } 376 }
385 377
386 void SetDecodedImage(const gfx::Image& image) { decoded_image_ = image; } 378 void SetDecodedImage(const gfx::Image& image) { decoded_image_ = image; }
387 379
388 private: 380 private:
389 gfx::Image decoded_image_; 381 gfx::Image decoded_image_;
390 }; 382 };
391 383
392 } // namespace 384 } // namespace
393 385
394 class RemoteSuggestionsProviderTest : public ::testing::Test { 386 class RemoteSuggestionsProviderImplTest : public ::testing::Test {
395 public: 387 public:
396 RemoteSuggestionsProviderTest() 388 RemoteSuggestionsProviderTest()
397 : params_manager_(ntp_snippets::kStudyName, 389 : params_manager_(ntp_snippets::kStudyName,
398 {{"content_suggestions_backend", 390 {{"content_suggestions_backend",
399 kTestContentSuggestionsServerEndpoint}, 391 kTestContentSuggestionsServerEndpoint},
400 {"fetching_personalization", "non_personal"}}), 392 {"fetching_personalization", "non_personal"}}),
401 fake_url_fetcher_factory_( 393 fake_url_fetcher_factory_(
402 /*default_factory=*/&failing_url_fetcher_factory_), 394 /*default_factory=*/&failing_url_fetcher_factory_),
403 test_url_(kTestContentSuggestionsServerWithAPIKey), 395 test_url_(kTestContentSuggestionsServerWithAPIKey),
404 user_classifier_(/*pref_service=*/nullptr), 396 user_classifier_(/*pref_service=*/nullptr),
405 image_fetcher_(nullptr), 397 image_fetcher_(nullptr),
406 image_decoder_(nullptr), 398 image_decoder_(nullptr),
407 database_(nullptr) { 399 database_(nullptr) {
408 RemoteSuggestionsProvider::RegisterProfilePrefs( 400 RemoteSuggestionsProviderImpl::RegisterProfilePrefs(
409 utils_.pref_service()->registry()); 401 utils_.pref_service()->registry());
410 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); 402 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry());
411 403
412 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); 404 EXPECT_TRUE(database_dir_.CreateUniqueTempDir());
413 } 405 }
414 406
415 ~RemoteSuggestionsProviderTest() override { 407 ~RemoteSuggestionsProviderImplTest() override {
416 // We need to run the message loop after deleting the database, because 408 // We need to run the message loop after deleting the database, because
417 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task 409 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task
418 // runner. Without this, we'd get reports of memory leaks. 410 // runner. Without this, we'd get reports of memory leaks.
419 base::RunLoop().RunUntilIdle(); 411 base::RunLoop().RunUntilIdle();
420 } 412 }
421 413
422 std::unique_ptr<RemoteSuggestionsProvider> MakeSnippetsService( 414 std::unique_ptr<RemoteSuggestionsProviderImpl> MakeSnippetsService(
423 bool set_empty_response = true) { 415 bool set_empty_response = true) {
424 auto service = MakeSnippetsServiceWithoutInitialization(); 416 auto service = MakeSnippetsServiceWithoutInitialization();
425 WaitForSnippetsServiceInitialization(service.get(), set_empty_response); 417 WaitForSnippetsServiceInitialization(service.get(), set_empty_response);
426 return service; 418 return service;
427 } 419 }
428 420
429 std::unique_ptr<RemoteSuggestionsProvider> 421 std::unique_ptr<RemoteSuggestionsProviderImpl>
430 MakeSnippetsServiceWithoutInitialization() { 422 MakeSnippetsServiceWithoutInitialization() {
431 scoped_refptr<base::SingleThreadTaskRunner> task_runner( 423 scoped_refptr<base::SingleThreadTaskRunner> task_runner(
432 base::ThreadTaskRunnerHandle::Get()); 424 base::ThreadTaskRunnerHandle::Get());
433 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = 425 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
434 new net::TestURLRequestContextGetter(task_runner.get()); 426 new net::TestURLRequestContextGetter(task_runner.get());
435 427
436 utils_.ResetSigninManager(); 428 utils_.ResetSigninManager();
437 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher = 429 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher =
438 base::MakeUnique<NTPSnippetsFetcher>( 430 base::MakeUnique<NTPSnippetsFetcher>(
439 utils_.fake_signin_manager(), fake_token_service_.get(), 431 utils_.fake_signin_manager(), fake_token_service_.get(),
440 std::move(request_context_getter), utils_.pref_service(), 432 std::move(request_context_getter), utils_.pref_service(),
441 &category_factory_, nullptr, base::Bind(&ParseJson), kAPIKey, 433 &category_factory_, nullptr, base::Bind(&ParseJson), kAPIKey,
442 &user_classifier_); 434 &user_classifier_);
443 435
444 utils_.fake_signin_manager()->SignIn("foo@bar.com"); 436 utils_.fake_signin_manager()->SignIn("foo@bar.com");
445 437
446 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>(); 438 auto image_fetcher = base::MakeUnique<NiceMock<MockImageFetcher>>();
447 439
448 image_fetcher_ = image_fetcher.get(); 440 image_fetcher_ = image_fetcher.get();
449 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_)); 441 EXPECT_CALL(*image_fetcher, SetImageFetcherDelegate(_));
450 auto image_decoder = base::MakeUnique<FakeImageDecoder>(); 442 auto image_decoder = base::MakeUnique<FakeImageDecoder>();
451 image_decoder_ = image_decoder.get(); 443 image_decoder_ = image_decoder.get();
452 EXPECT_FALSE(observer_); 444 EXPECT_FALSE(observer_);
453 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>(); 445 observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>();
454 auto database = base::MakeUnique<RemoteSuggestionsDatabase>( 446 auto database = base::MakeUnique<RemoteSuggestionsDatabase>(
455 database_dir_.GetPath(), task_runner); 447 database_dir_.GetPath(), task_runner);
456 database_ = database.get(); 448 database_ = database.get();
457 return base::MakeUnique<RemoteSuggestionsProvider>( 449 return base::MakeUnique<RemoteSuggestionsProviderImpl>(
458 observer_.get(), &category_factory_, utils_.pref_service(), "fr", 450 observer_.get(), &category_factory_, utils_.pref_service(), "fr",
459 &user_classifier_, &scheduler_, std::move(snippets_fetcher), 451 &user_classifier_, std::move(snippets_fetcher),
460 std::move(image_fetcher), std::move(image_decoder), 452 std::move(image_fetcher), std::move(image_decoder), std::move(database),
461 std::move(database),
462 base::MakeUnique<RemoteSuggestionsStatusService>( 453 base::MakeUnique<RemoteSuggestionsStatusService>(
463 utils_.fake_signin_manager(), utils_.pref_service())); 454 utils_.fake_signin_manager(), utils_.pref_service()));
464 } 455 }
465 456
466 void WaitForSnippetsServiceInitialization(RemoteSuggestionsProvider* service, 457 void WaitForSnippetsServiceInitialization(
467 bool set_empty_response) { 458 RemoteSuggestionsProviderImpl* service,
468 EXPECT_EQ(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 459 bool set_empty_response) {
460 EXPECT_EQ(RemoteSuggestionsProviderImpl::State::NOT_INITED,
461 service->state_);
469 462
470 // Add an initial fetch response, as the service tries to fetch when there 463 // Add an initial fetch response, as the service tries to fetch when there
471 // is nothing in the DB. 464 // is nothing in the DB.
472 if (set_empty_response) { 465 if (set_empty_response) {
473 SetUpFetchResponse(GetTestJson(std::vector<std::string>())); 466 SetUpFetchResponse(GetTestJson(std::vector<std::string>()));
474 } 467 }
475 468
476 // TODO(treib): Find a better way to wait for initialization to finish. 469 // TODO(treib): Find a better way to wait for initialization to finish.
477 base::RunLoop().RunUntilIdle(); 470 base::RunLoop().RunUntilIdle();
478 EXPECT_NE(RemoteSuggestionsProvider::State::NOT_INITED, service->state_); 471 EXPECT_NE(RemoteSuggestionsProviderImpl::State::NOT_INITED,
472 service->state_);
479 } 473 }
480 474
481 void ResetSnippetsService( 475 void ResetSnippetsService(
482 std::unique_ptr<RemoteSuggestionsProvider>* service) { 476 std::unique_ptr<RemoteSuggestionsProviderImpl>* service) {
483 service->reset(); 477 service->reset();
484 observer_.reset(); 478 observer_.reset();
485 *service = MakeSnippetsService(); 479 *service = MakeSnippetsService();
486 } 480 }
487 481
488 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) { 482 ContentSuggestion::ID MakeArticleID(const std::string& id_within_category) {
489 return ContentSuggestion::ID(articles_category(), id_within_category); 483 return ContentSuggestion::ID(articles_category(), id_within_category);
490 } 484 }
491 485
492 Category articles_category() { 486 Category articles_category() {
493 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES); 487 return category_factory_.FromKnownCategory(KnownCategories::ARTICLES);
494 } 488 }
495 489
496 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) { 490 ContentSuggestion::ID MakeOtherID(const std::string& id_within_category) {
497 return ContentSuggestion::ID(other_category(), id_within_category); 491 return ContentSuggestion::ID(other_category(), id_within_category);
498 } 492 }
499 493
500 Category other_category() { return category_factory_.FromRemoteCategory(2); } 494 Category other_category() { return category_factory_.FromRemoteCategory(2); }
501 495
502 Category unknown_category() { 496 Category unknown_category() {
503 return category_factory_.FromRemoteCategory(kUnknownRemoteCategoryId); 497 return category_factory_.FromRemoteCategory(kUnknownRemoteCategoryId);
504 } 498 }
505 499
506 protected: 500 protected:
507 const GURL& test_url() { return test_url_; } 501 const GURL& test_url() { return test_url_; }
508 FakeContentSuggestionsProviderObserver& observer() { return *observer_; } 502 FakeContentSuggestionsProviderObserver& observer() { return *observer_; }
509 MockScheduler& mock_scheduler() { return scheduler_; }
510 // TODO(tschumann): Make this a strict-mock. We want to avoid unneccesary 503 // TODO(tschumann): Make this a strict-mock. We want to avoid unneccesary
511 // network requests. 504 // network requests.
512 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; } 505 NiceMock<MockImageFetcher>* image_fetcher() { return image_fetcher_; }
513 FakeImageDecoder* image_decoder() { return image_decoder_; } 506 FakeImageDecoder* image_decoder() { return image_decoder_; }
514 PrefService* pref_service() { return utils_.pref_service(); } 507 PrefService* pref_service() { return utils_.pref_service(); }
515 RemoteSuggestionsDatabase* database() { return database_; } 508 RemoteSuggestionsDatabase* database() { return database_; }
516 509
517 // Provide the json to be returned by the fake fetcher. 510 // Provide the json to be returned by the fake fetcher.
518 void SetUpFetchResponse(const std::string& json) { 511 void SetUpFetchResponse(const std::string& json) {
519 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK, 512 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK,
520 net::URLRequestStatus::SUCCESS); 513 net::URLRequestStatus::SUCCESS);
521 } 514 }
522 515
523 // Have the fake fetcher fail due to a HTTP error like a 404. 516 // Have the fake fetcher fail due to a HTTP error like a 404.
524 void SetUpHttpError() { 517 void SetUpHttpError() {
525 fake_url_fetcher_factory_.SetFakeResponse(test_url_, /*json=*/std::string(), 518 fake_url_fetcher_factory_.SetFakeResponse(test_url_, /*json=*/std::string(),
526 net::HTTP_NOT_FOUND, 519 net::HTTP_NOT_FOUND,
527 net::URLRequestStatus::SUCCESS); 520 net::URLRequestStatus::SUCCESS);
528 } 521 }
529 522
530 void LoadFromJSONString(RemoteSuggestionsProvider* service, 523 void LoadFromJSONString(RemoteSuggestionsProviderImpl* service,
531 const std::string& json) { 524 const std::string& json) {
532 SetUpFetchResponse(json); 525 SetUpFetchResponse(json);
533 service->FetchSnippets(true); 526 service->FetchSnippets(true);
534 base::RunLoop().RunUntilIdle(); 527 base::RunLoop().RunUntilIdle();
535 } 528 }
536 529
537 void LoadMoreFromJSONString(RemoteSuggestionsProvider* service, 530 void LoadMoreFromJSONString(RemoteSuggestionsProviderImpl* service,
538 const Category& category, 531 const Category& category,
539 const std::string& json, 532 const std::string& json,
540 const std::set<std::string>& known_ids, 533 const std::set<std::string>& known_ids,
541 FetchDoneCallback callback) { 534 FetchDoneCallback callback) {
542 SetUpFetchResponse(json); 535 SetUpFetchResponse(json);
543 service->Fetch(category, known_ids, callback); 536 service->Fetch(category, known_ids, callback);
544 base::RunLoop().RunUntilIdle(); 537 base::RunLoop().RunUntilIdle();
545 } 538 }
546 539
547 private: 540 private:
548 variations::testing::VariationParamsManager params_manager_; 541 variations::testing::VariationParamsManager params_manager_;
549 test::RemoteSuggestionsTestUtils utils_; 542 test::RemoteSuggestionsTestUtils utils_;
550 base::MessageLoop message_loop_; 543 base::MessageLoop message_loop_;
551 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; 544 FailingFakeURLFetcherFactory failing_url_fetcher_factory_;
552 // Instantiation of factory automatically sets itself as URLFetcher's factory. 545 // Instantiation of factory automatically sets itself as URLFetcher's factory.
553 net::FakeURLFetcherFactory fake_url_fetcher_factory_; 546 net::FakeURLFetcherFactory fake_url_fetcher_factory_;
554 const GURL test_url_; 547 const GURL test_url_;
555 std::unique_ptr<OAuth2TokenService> fake_token_service_; 548 std::unique_ptr<OAuth2TokenService> fake_token_service_;
556 UserClassifier user_classifier_; 549 UserClassifier user_classifier_;
557 NiceMock<MockScheduler> scheduler_;
558 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; 550 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_;
559 CategoryFactory category_factory_; 551 CategoryFactory category_factory_;
560 NiceMock<MockImageFetcher>* image_fetcher_; 552 NiceMock<MockImageFetcher>* image_fetcher_;
561 FakeImageDecoder* image_decoder_; 553 FakeImageDecoder* image_decoder_;
562 554
563 base::ScopedTempDir database_dir_; 555 base::ScopedTempDir database_dir_;
564 RemoteSuggestionsDatabase* database_; 556 RemoteSuggestionsDatabase* database_;
565 557
566 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderTest); 558 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderImplTest);
567 }; 559 };
568 560
569 TEST_F(RemoteSuggestionsProviderTest, ScheduleOnStart) { 561 TEST_F(RemoteSuggestionsProviderImplTest, Full) {
570 // We should get two |Schedule| calls: The first when initialization
571 // completes, the second one after the automatic (since the service doesn't
572 // have any data yet) fetch finishes.
573 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
574 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
575 auto service = MakeSnippetsService();
576
577 // When we have no snippets are all, loading the service initiates a fetch.
578 EXPECT_EQ("OK", service->snippets_fetcher()->last_status());
579 }
580
581 TEST_F(RemoteSuggestionsProviderTest, DontRescheduleOnStart) {
582 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
583 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
584 SetUpFetchResponse(GetTestJson({GetSnippet()}));
585 auto service = MakeSnippetsService(/*set_empty_response=*/false);
586
587 // When recreating the service, we should not get any |Schedule| calls:
588 // 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
590 // should happen.
591 Mock::VerifyAndClearExpectations(&mock_scheduler());
592 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0);
593 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
594 ResetSnippetsService(&service);
595 }
596
597 TEST_F(RemoteSuggestionsProviderTest, RescheduleAfterSuccessfulFetch) {
598 // We should get two |Schedule| calls: The first when initialization
599 // completes, the second one after the automatic (since the service doesn't
600 // have any data yet) fetch finishes.
601 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
602 auto service = MakeSnippetsService();
603
604 // A successful fetch should trigger another |Schedule|.
605 EXPECT_CALL(mock_scheduler(), Schedule(_, _));
606 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()}));
607 }
608
609 TEST_F(RemoteSuggestionsProviderTest, DontRescheduleAfterFailedFetch) {
610 // We should get two |Schedule| calls: The first when initialization
611 // completes, the second one after the automatic (since the service doesn't
612 // have any data yet) fetch finishes.
613 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
614 auto service = MakeSnippetsService();
615
616 // A failed fetch should NOT trigger another |Schedule|.
617 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0);
618 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()}));
619 }
620
621 TEST_F(RemoteSuggestionsProviderTest, IgnoreRescheduleBeforeInit) {
622 // We should get two |Schedule| calls: The first when initialization
623 // completes, the second one after the automatic (since the service doesn't
624 // have any data yet) fetch finishes.
625 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
626 // The |RescheduleFetching| call shouldn't do anything (in particular not
627 // result in an |Unschedule|), since the service isn't initialized yet.
628 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
629 auto service = MakeSnippetsServiceWithoutInitialization();
630 service->RescheduleFetching(false);
631 WaitForSnippetsServiceInitialization(service.get(),
632 /*set_empty_response=*/true);
633 }
634
635 TEST_F(RemoteSuggestionsProviderTest, HandleForcedRescheduleBeforeInit) {
636 {
637 InSequence s;
638 // The |RescheduleFetching| call with force=true should result in an
639 // |Unschedule|, since the service isn't initialized yet.
640 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1);
641 // We should get two |Schedule| calls: The first when initialization
642 // completes, the second one after the automatic (since the service doesn't
643 // have any data yet) fetch finishes.
644 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
645 }
646 auto service = MakeSnippetsServiceWithoutInitialization();
647 service->RescheduleFetching(true);
648 WaitForSnippetsServiceInitialization(service.get(),
649 /*set_empty_response=*/true);
650 }
651
652 TEST_F(RemoteSuggestionsProviderTest, RescheduleOnStateChange) {
653 {
654 InSequence s;
655 // Initial startup.
656 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
657 // Service gets disabled.
658 EXPECT_CALL(mock_scheduler(), Unschedule());
659 // Service gets enabled again.
660 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
661 }
662 auto service = MakeSnippetsService();
663 ASSERT_TRUE(service->ready());
664
665 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN,
666 RemoteSuggestionsStatus::EXPLICITLY_DISABLED);
667 ASSERT_FALSE(service->ready());
668 base::RunLoop().RunUntilIdle();
669
670 service->OnStatusChanged(RemoteSuggestionsStatus::EXPLICITLY_DISABLED,
671 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT);
672 ASSERT_TRUE(service->ready());
673 base::RunLoop().RunUntilIdle();
674 }
675
676 TEST_F(RemoteSuggestionsProviderTest, DontUnscheduleOnShutdown) {
677 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2);
678 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0);
679
680 auto service = MakeSnippetsService();
681
682 service.reset();
683 base::RunLoop().RunUntilIdle();
684 }
685
686 TEST_F(RemoteSuggestionsProviderTest, Full) {
687 std::string json_str(GetTestJson({GetSnippet()})); 562 std::string json_str(GetTestJson({GetSnippet()}));
688 563
689 auto service = MakeSnippetsService(); 564 auto service = MakeSnippetsService();
690 565
691 LoadFromJSONString(service.get(), json_str); 566 LoadFromJSONString(service.get(), json_str);
692 567
693 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 568 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
694 SizeIs(1)); 569 SizeIs(1));
695 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 570 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
696 571
697 const ContentSuggestion& suggestion = 572 const ContentSuggestion& suggestion =
698 observer().SuggestionsForCategory(articles_category()).front(); 573 observer().SuggestionsForCategory(articles_category()).front();
699 574
700 EXPECT_EQ(MakeArticleID(kSnippetUrl), suggestion.id()); 575 EXPECT_EQ(MakeArticleID(kSnippetUrl), suggestion.id());
701 EXPECT_EQ(kSnippetTitle, base::UTF16ToUTF8(suggestion.title())); 576 EXPECT_EQ(kSnippetTitle, base::UTF16ToUTF8(suggestion.title()));
702 EXPECT_EQ(kSnippetText, base::UTF16ToUTF8(suggestion.snippet_text())); 577 EXPECT_EQ(kSnippetText, base::UTF16ToUTF8(suggestion.snippet_text()));
703 EXPECT_EQ(GetDefaultCreationTime(), suggestion.publish_date()); 578 EXPECT_EQ(GetDefaultCreationTime(), suggestion.publish_date());
704 EXPECT_EQ(kSnippetPublisherName, 579 EXPECT_EQ(kSnippetPublisherName,
705 base::UTF16ToUTF8(suggestion.publisher_name())); 580 base::UTF16ToUTF8(suggestion.publisher_name()));
706 EXPECT_EQ(GURL(kSnippetAmpUrl), suggestion.amp_url()); 581 EXPECT_EQ(GURL(kSnippetAmpUrl), suggestion.amp_url());
707 } 582 }
708 583
709 TEST_F(RemoteSuggestionsProviderTest, CategoryTitle) { 584 TEST_F(RemoteSuggestionsProviderImplTest, CategoryTitle) {
710 const base::string16 test_default_title = 585 const base::string16 test_default_title =
711 base::UTF8ToUTF16(kTestJsonDefaultCategoryTitle); 586 base::UTF8ToUTF16(kTestJsonDefaultCategoryTitle);
712 587
713 // Don't send an initial response -- we want to test what happens without any 588 // Don't send an initial response -- we want to test what happens without any
714 // server status. 589 // server status.
715 auto service = MakeSnippetsService(/*set_empty_response=*/false); 590 auto service = MakeSnippetsService(/*set_empty_response=*/false);
716 591
717 // The articles category should be there by default, and have a title. 592 // The articles category should be there by default, and have a title.
718 CategoryInfo info_before = service->GetCategoryInfo(articles_category()); 593 CategoryInfo info_before = service->GetCategoryInfo(articles_category());
719 ASSERT_THAT(info_before.title(), Not(IsEmpty())); 594 ASSERT_THAT(info_before.title(), Not(IsEmpty()));
(...skipping 14 matching lines...) Expand all
734 // Make sure we updated the title in the CategoryInfo. 609 // Make sure we updated the title in the CategoryInfo.
735 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category()); 610 CategoryInfo info_with_title = service->GetCategoryInfo(articles_category());
736 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title()))); 611 EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title())));
737 EXPECT_THAT(test_default_title, Eq(info_with_title.title())); 612 EXPECT_THAT(test_default_title, Eq(info_with_title.title()));
738 EXPECT_THAT(info_before.has_more_action(), Eq(true)); 613 EXPECT_THAT(info_before.has_more_action(), Eq(true));
739 EXPECT_THAT(info_before.has_reload_action(), Eq(true)); 614 EXPECT_THAT(info_before.has_reload_action(), Eq(true));
740 EXPECT_THAT(info_before.has_view_all_action(), Eq(false)); 615 EXPECT_THAT(info_before.has_view_all_action(), Eq(false));
741 EXPECT_THAT(info_before.show_if_empty(), Eq(true)); 616 EXPECT_THAT(info_before.show_if_empty(), Eq(true));
742 } 617 }
743 618
744 TEST_F(RemoteSuggestionsProviderTest, MultipleCategories) { 619 TEST_F(RemoteSuggestionsProviderImplTest, MultipleCategories) {
745 std::string json_str( 620 std::string json_str(
746 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 621 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}));
747 622
748 auto service = MakeSnippetsService(); 623 auto service = MakeSnippetsService();
749 624
750 LoadFromJSONString(service.get(), json_str); 625 LoadFromJSONString(service.get(), json_str);
751 626
752 ASSERT_THAT(observer().statuses(), 627 ASSERT_THAT(observer().statuses(),
753 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{ 628 Eq(std::map<Category, CategoryStatus, Category::CompareByID>{
754 {articles_category(), CategoryStatus::AVAILABLE}, 629 {articles_category(), CategoryStatus::AVAILABLE},
(...skipping 26 matching lines...) Expand all
781 EXPECT_EQ(MakeOtherID(std::string(kSnippetUrl) + "/1"), suggestion.id()); 656 EXPECT_EQ(MakeOtherID(std::string(kSnippetUrl) + "/1"), suggestion.id());
782 EXPECT_EQ(kSnippetTitle, base::UTF16ToUTF8(suggestion.title())); 657 EXPECT_EQ(kSnippetTitle, base::UTF16ToUTF8(suggestion.title()));
783 EXPECT_EQ(kSnippetText, base::UTF16ToUTF8(suggestion.snippet_text())); 658 EXPECT_EQ(kSnippetText, base::UTF16ToUTF8(suggestion.snippet_text()));
784 EXPECT_EQ(GetDefaultCreationTime(), suggestion.publish_date()); 659 EXPECT_EQ(GetDefaultCreationTime(), suggestion.publish_date());
785 EXPECT_EQ(kSnippetPublisherName, 660 EXPECT_EQ(kSnippetPublisherName,
786 base::UTF16ToUTF8(suggestion.publisher_name())); 661 base::UTF16ToUTF8(suggestion.publisher_name()));
787 EXPECT_EQ(GURL(kSnippetAmpUrl), suggestion.amp_url()); 662 EXPECT_EQ(GURL(kSnippetAmpUrl), suggestion.amp_url());
788 } 663 }
789 } 664 }
790 665
791 TEST_F(RemoteSuggestionsProviderTest, ArticleCategoryInfo) { 666 TEST_F(RemoteSuggestionsProviderImplTest, ArticleCategoryInfo) {
792 auto service = MakeSnippetsService(); 667 auto service = MakeSnippetsService();
793 CategoryInfo article_info = service->GetCategoryInfo(articles_category()); 668 CategoryInfo article_info = service->GetCategoryInfo(articles_category());
794 EXPECT_THAT(article_info.has_more_action(), Eq(true)); 669 EXPECT_THAT(article_info.has_more_action(), Eq(true));
795 EXPECT_THAT(article_info.has_reload_action(), Eq(true)); 670 EXPECT_THAT(article_info.has_reload_action(), Eq(true));
796 EXPECT_THAT(article_info.has_view_all_action(), Eq(false)); 671 EXPECT_THAT(article_info.has_view_all_action(), Eq(false));
797 EXPECT_THAT(article_info.show_if_empty(), Eq(true)); 672 EXPECT_THAT(article_info.show_if_empty(), Eq(true));
798 } 673 }
799 674
800 TEST_F(RemoteSuggestionsProviderTest, ExperimentalCategoryInfo) { 675 TEST_F(RemoteSuggestionsProviderImplTest, ExperimentalCategoryInfo) {
801 auto service = MakeSnippetsService(); 676 auto service = MakeSnippetsService();
802 677
803 // Load data with multiple categories so that a new experimental category gets 678 // Load data with multiple categories so that a new experimental category gets
804 // registered. 679 // registered.
805 LoadFromJSONString(service.get(), 680 LoadFromJSONString(service.get(),
806 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 681 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)},
807 kUnknownRemoteCategoryId)); 682 kUnknownRemoteCategoryId));
808 CategoryInfo info = service->GetCategoryInfo(unknown_category()); 683 CategoryInfo info = service->GetCategoryInfo(unknown_category());
809 EXPECT_THAT(info.has_more_action(), Eq(false)); 684 EXPECT_THAT(info.has_more_action(), Eq(false));
810 EXPECT_THAT(info.has_reload_action(), Eq(false)); 685 EXPECT_THAT(info.has_reload_action(), Eq(false));
811 EXPECT_THAT(info.has_view_all_action(), Eq(false)); 686 EXPECT_THAT(info.has_view_all_action(), Eq(false));
812 EXPECT_THAT(info.show_if_empty(), Eq(false)); 687 EXPECT_THAT(info.show_if_empty(), Eq(false));
813 } 688 }
814 689
815 TEST_F(RemoteSuggestionsProviderTest, PersistCategoryInfos) { 690 TEST_F(RemoteSuggestionsProviderImplTest, PersistCategoryInfos) {
816 auto service = MakeSnippetsService(); 691 auto service = MakeSnippetsService();
817 692
818 LoadFromJSONString(service.get(), 693 LoadFromJSONString(service.get(),
819 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}, 694 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)},
820 kUnknownRemoteCategoryId)); 695 kUnknownRemoteCategoryId));
821 696
822 ASSERT_EQ(observer().StatusForCategory(articles_category()), 697 ASSERT_EQ(observer().StatusForCategory(articles_category()),
823 CategoryStatus::AVAILABLE); 698 CategoryStatus::AVAILABLE);
824 ASSERT_EQ(observer().StatusForCategory(unknown_category()), 699 ASSERT_EQ(observer().StatusForCategory(unknown_category()),
825 CategoryStatus::AVAILABLE); 700 CategoryStatus::AVAILABLE);
(...skipping 19 matching lines...) Expand all
845 720
846 CategoryInfo info_articles_after = 721 CategoryInfo info_articles_after =
847 service->GetCategoryInfo(articles_category()); 722 service->GetCategoryInfo(articles_category());
848 CategoryInfo info_unknown_after = 723 CategoryInfo info_unknown_after =
849 service->GetCategoryInfo(unknown_category()); 724 service->GetCategoryInfo(unknown_category());
850 725
851 EXPECT_EQ(info_articles_before.title(), info_articles_after.title()); 726 EXPECT_EQ(info_articles_before.title(), info_articles_after.title());
852 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title()); 727 EXPECT_EQ(info_unknown_before.title(), info_unknown_after.title());
853 } 728 }
854 729
855 TEST_F(RemoteSuggestionsProviderTest, PersistSuggestions) { 730 TEST_F(RemoteSuggestionsProviderImplTest, PersistSuggestions) {
856 auto service = MakeSnippetsService(); 731 auto service = MakeSnippetsService();
857 732
858 LoadFromJSONString(service.get(), 733 LoadFromJSONString(service.get(),
859 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 734 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}));
860 735
861 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 736 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
862 SizeIs(1)); 737 SizeIs(1));
863 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 738 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
864 739
865 // Recreate the service to simulate a Chrome restart. 740 // Recreate the service to simulate a Chrome restart.
866 ResetSnippetsService(&service); 741 ResetSnippetsService(&service);
867 742
868 // The suggestions in both categories should have been restored. 743 // The suggestions in both categories should have been restored.
869 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 744 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
870 SizeIs(1)); 745 SizeIs(1));
871 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 746 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
872 } 747 }
873 748
874 TEST_F(RemoteSuggestionsProviderTest, DontNotifyIfNotAvailable) { 749 TEST_F(RemoteSuggestionsProviderImplTest, DontNotifyIfNotAvailable) {
875 // Get some suggestions into the database. 750 // Get some suggestions into the database.
876 auto service = MakeSnippetsService(); 751 auto service = MakeSnippetsService();
877 LoadFromJSONString(service.get(), 752 LoadFromJSONString(service.get(),
878 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)})); 753 GetMultiCategoryJson({GetSnippetN(0)}, {GetSnippetN(1)}));
879 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()), 754 ASSERT_THAT(observer().SuggestionsForCategory(articles_category()),
880 SizeIs(1)); 755 SizeIs(1));
881 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1)); 756 ASSERT_THAT(observer().SuggestionsForCategory(other_category()), SizeIs(1));
882 757
883 service.reset(); 758 service.reset();
884 759
885 // Set the pref that disables remote suggestions. 760 // Set the pref that disables remote suggestions.
886 pref_service()->SetBoolean(prefs::kEnableSnippets, false); 761 pref_service()->SetBoolean(prefs::kEnableSnippets, false);
887 762
888 // Recreate the service to simulate a Chrome start. 763 // Recreate the service to simulate a Chrome start.
889 ResetSnippetsService(&service); 764 ResetSnippetsService(&service);
890 765
891 ASSERT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_)); 766 ASSERT_THAT(RemoteSuggestionsProviderImpl::State::DISABLED,
767 Eq(service->state_));
892 768
893 // Now the observer should not have received any suggestions. 769 // Now the observer should not have received any suggestions.
894 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), 770 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()),
895 IsEmpty()); 771 IsEmpty());
896 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty()); 772 EXPECT_THAT(observer().SuggestionsForCategory(other_category()), IsEmpty());
897 } 773 }
898 774
899 TEST_F(RemoteSuggestionsProviderTest, Clear) { 775 TEST_F(RemoteSuggestionsProviderImplTest, Clear) {
900 auto service = MakeSnippetsService(); 776 auto service = MakeSnippetsService();
901 777
902 std::string json_str(GetTestJson({GetSnippet()})); 778 std::string json_str(GetTestJson({GetSnippet()}));
903 779
904 LoadFromJSONString(service.get(), json_str); 780 LoadFromJSONString(service.get(), json_str);
905 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 781 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
906 782
907 service->ClearCachedSuggestions(articles_category()); 783 service->ClearCachedSuggestions(articles_category());
908 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 784 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
909 } 785 }
910 786
911 TEST_F(RemoteSuggestionsProviderTest, ReplaceSnippets) { 787 TEST_F(RemoteSuggestionsProviderImplTest, ReplaceSnippets) {
912 auto service = MakeSnippetsService(); 788 auto service = MakeSnippetsService();
913 789
914 std::string first("http://first"); 790 std::string first("http://first");
915 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(first)})); 791 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(first)}));
916 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), 792 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()),
917 ElementsAre(IdEq(first))); 793 ElementsAre(IdEq(first)));
918 794
919 std::string second("http://second"); 795 std::string second("http://second");
920 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(second)})); 796 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(second)}));
921 // The snippets loaded last replace all that was loaded previously. 797 // The snippets loaded last replace all that was loaded previously.
922 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), 798 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()),
923 ElementsAre(IdEq(second))); 799 ElementsAre(IdEq(second)));
924 } 800 }
925 801
926 TEST_F(RemoteSuggestionsProviderTest, LoadsAdditionalSnippets) { 802 TEST_F(RemoteSuggestionsProviderImplTest, LoadsAdditionalSnippets) {
927 auto service = MakeSnippetsService(); 803 auto service = MakeSnippetsService();
928 804
929 LoadFromJSONString(service.get(), 805 LoadFromJSONString(service.get(),
930 GetTestJson({GetSnippetWithUrl("http://first")})); 806 GetTestJson({GetSnippetWithUrl("http://first")}));
931 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), 807 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()),
932 ElementsAre(IdEq("http://first"))); 808 ElementsAre(IdEq("http://first")));
933 809
934 auto expect_only_second_suggestion_received = base::Bind([]( 810 auto expect_only_second_suggestion_received = base::Bind([](
935 Status status, std::vector<ContentSuggestion> suggestions) { 811 Status status, std::vector<ContentSuggestion> suggestions) {
936 EXPECT_THAT(suggestions, SizeIs(1)); 812 EXPECT_THAT(suggestions, SizeIs(1));
(...skipping 29 matching lines...) Expand all
966 // The tests TestMergingFetchedMoreSnippetsFillup and 842 // The tests TestMergingFetchedMoreSnippetsFillup and
967 // TestMergingFetchedMoreSnippetsReplaceAll simulate the following user story: 843 // TestMergingFetchedMoreSnippetsReplaceAll simulate the following user story:
968 // 1) fetch suggestions in NTP A 844 // 1) fetch suggestions in NTP A
969 // 2) fetch more suggestions in NTP A. 845 // 2) fetch more suggestions in NTP A.
970 // 3) open new NTP B: See the last 10 results visible in step 2). 846 // 3) open new NTP B: See the last 10 results visible in step 2).
971 // 4) fetch more suggestions in NTP B. Make sure no results from step 1) which 847 // 4) fetch more suggestions in NTP B. Make sure no results from step 1) which
972 // were superseded in step 2) get merged back in again. 848 // were superseded in step 2) get merged back in again.
973 // TODO(tschumann): Test step 4) on a higher level instead of peeking into the 849 // TODO(tschumann): Test step 4) on a higher level instead of peeking into the
974 // internal 'dismissed' data. The proper check is to make sure we tell the 850 // internal 'dismissed' data. The proper check is to make sure we tell the
975 // backend to exclude these snippets. 851 // backend to exclude these snippets.
976 TEST_F(RemoteSuggestionsProviderTest, TestMergingFetchedMoreSnippetsFillup) { 852 TEST_F(RemoteSuggestionsProviderImplTest,
853 TestMergingFetchedMoreSnippetsFillup) {
977 auto service = MakeSnippetsService(/*set_empty_response=*/false); 854 auto service = MakeSnippetsService(/*set_empty_response=*/false);
978 LoadFromJSONString( 855 LoadFromJSONString(
979 service.get(), 856 service.get(),
980 GetTestJson( 857 GetTestJson(
981 {GetSnippetWithUrl("http://id-1"), GetSnippetWithUrl("http://id-2"), 858 {GetSnippetWithUrl("http://id-1"), GetSnippetWithUrl("http://id-2"),
982 GetSnippetWithUrl("http://id-3"), GetSnippetWithUrl("http://id-4"), 859 GetSnippetWithUrl("http://id-3"), GetSnippetWithUrl("http://id-4"),
983 GetSnippetWithUrl("http://id-5"), GetSnippetWithUrl("http://id-6"), 860 GetSnippetWithUrl("http://id-5"), GetSnippetWithUrl("http://id-6"),
984 GetSnippetWithUrl("http://id-7"), GetSnippetWithUrl("http://id-8"), 861 GetSnippetWithUrl("http://id-7"), GetSnippetWithUrl("http://id-8"),
985 GetSnippetWithUrl("http://id-9"), 862 GetSnippetWithUrl("http://id-9"),
986 GetSnippetWithUrl("http://id-10")})); 863 GetSnippetWithUrl("http://id-10")}));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 IdWithinCategoryEq("http://id-5"), IdWithinCategoryEq("http://id-6"), 896 IdWithinCategoryEq("http://id-5"), IdWithinCategoryEq("http://id-6"),
1020 IdWithinCategoryEq("http://id-7"), IdWithinCategoryEq("http://id-8"), 897 IdWithinCategoryEq("http://id-7"), IdWithinCategoryEq("http://id-8"),
1021 IdWithinCategoryEq("http://id-9"), IdWithinCategoryEq("http://id-10"), 898 IdWithinCategoryEq("http://id-9"), IdWithinCategoryEq("http://id-10"),
1022 IdWithinCategoryEq("http://more-id-1"), 899 IdWithinCategoryEq("http://more-id-1"),
1023 IdWithinCategoryEq("http://more-id-2"))); 900 IdWithinCategoryEq("http://more-id-2")));
1024 // Verify the superseded suggestions got marked as dismissed. 901 // Verify the superseded suggestions got marked as dismissed.
1025 EXPECT_THAT(service->GetDismissedSnippetsForTesting(articles_category()), 902 EXPECT_THAT(service->GetDismissedSnippetsForTesting(articles_category()),
1026 ElementsAre(IdEq("http://id-1"), IdEq("http://id-2"))); 903 ElementsAre(IdEq("http://id-1"), IdEq("http://id-2")));
1027 } 904 }
1028 905
1029 TEST_F(RemoteSuggestionsProviderTest, 906 TEST_F(RemoteSuggestionsProviderImplTest,
1030 TestMergingFetchedMoreSnippetsReplaceAll) { 907 TestMergingFetchedMoreSnippetsReplaceAll) {
1031 auto service = MakeSnippetsService(/*set_empty_response=*/false); 908 auto service = MakeSnippetsService(/*set_empty_response=*/false);
1032 LoadFromJSONString( 909 LoadFromJSONString(
1033 service.get(), 910 service.get(),
1034 GetTestJson( 911 GetTestJson(
1035 {GetSnippetWithUrl("http://id-1"), GetSnippetWithUrl("http://id-2"), 912 {GetSnippetWithUrl("http://id-1"), GetSnippetWithUrl("http://id-2"),
1036 GetSnippetWithUrl("http://id-3"), GetSnippetWithUrl("http://id-4"), 913 GetSnippetWithUrl("http://id-3"), GetSnippetWithUrl("http://id-4"),
1037 GetSnippetWithUrl("http://id-5"), GetSnippetWithUrl("http://id-6"), 914 GetSnippetWithUrl("http://id-5"), GetSnippetWithUrl("http://id-6"),
1038 GetSnippetWithUrl("http://id-7"), GetSnippetWithUrl("http://id-8"), 915 GetSnippetWithUrl("http://id-7"), GetSnippetWithUrl("http://id-8"),
1039 GetSnippetWithUrl("http://id-9"), 916 GetSnippetWithUrl("http://id-9"),
1040 GetSnippetWithUrl("http://id-10")})); 917 GetSnippetWithUrl("http://id-10")}));
1041 EXPECT_THAT( 918 EXPECT_THAT(
1042 observer().SuggestionsForCategory(articles_category()), 919 observer().SuggestionsForCategory(articles_category()),
1043 ElementsAre( 920 ElementsAre(
1044 IdWithinCategoryEq("http://id-1"), IdWithinCategoryEq("http://id-2"), 921 IdWithinCategoryEq("http://id-1"), IdWithinCategoryEq("http://id-2"),
1045 IdWithinCategoryEq("http://id-3"), IdWithinCategoryEq("http://id-4"), 922 IdWithinCategoryEq("http://id-3"), IdWithinCategoryEq("http://id-4"),
1046 IdWithinCategoryEq("http://id-5"), IdWithinCategoryEq("http://id-6"), 923 IdWithinCategoryEq("http://id-5"), IdWithinCategoryEq("http://id-6"),
1047 IdWithinCategoryEq("http://id-7"), IdWithinCategoryEq("http://id-8"), 924 IdWithinCategoryEq("http://id-7"), IdWithinCategoryEq("http://id-8"),
1048 IdWithinCategoryEq("http://id-9"), 925 IdWithinCategoryEq("http://id-9"),
1049 IdWithinCategoryEq("http://id-10"))); 926 IdWithinCategoryEq("http://id-10")));
1050 927
1051 auto expect_receiving_ten_new_snippets = 928 auto expect_receiving_ten_new_snippets =
1052 base::Bind([](Status status, std::vector<ContentSuggestion> suggestions) { 929 base::Bind([](Status status, std::vector<ContentSuggestion> suggestions) {
1053 EXPECT_THAT(suggestions, ElementsAre( 930 EXPECT_THAT(suggestions,
1054 IdWithinCategoryEq("http://more-id-1"), 931 ElementsAre(IdWithinCategoryEq("http://more-id-1"),
1055 IdWithinCategoryEq("http://more-id-2"), 932 IdWithinCategoryEq("http://more-id-2"),
1056 IdWithinCategoryEq("http://more-id-3"), 933 IdWithinCategoryEq("http://more-id-3"),
1057 IdWithinCategoryEq("http://more-id-4"), 934 IdWithinCategoryEq("http://more-id-4"),
1058 IdWithinCategoryEq("http://more-id-5"), 935 IdWithinCategoryEq("http://more-id-5"),
1059 IdWithinCategoryEq("http://more-id-6"), 936 IdWithinCategoryEq("http://more-id-6"),
1060 IdWithinCategoryEq("http://more-id-7"), 937 IdWithinCategoryEq("http://more-id-7"),
1061 IdWithinCategoryEq("http://more-id-8"), 938 IdWithinCategoryEq("http://more-id-8"),
1062 IdWithinCategoryEq("http://more-id-9"), 939 IdWithinCategoryEq("http://more-id-9"),
1063 IdWithinCategoryEq("http://more-id-10"))); 940 IdWithinCategoryEq("http://more-id-10")));
1064 }); 941 });
1065 LoadMoreFromJSONString( 942 LoadMoreFromJSONString(
1066 service.get(), articles_category(), 943 service.get(), articles_category(),
1067 GetTestJson({GetSnippetWithUrl("http://more-id-1"), 944 GetTestJson({GetSnippetWithUrl("http://more-id-1"),
1068 GetSnippetWithUrl("http://more-id-2"), 945 GetSnippetWithUrl("http://more-id-2"),
1069 GetSnippetWithUrl("http://more-id-3"), 946 GetSnippetWithUrl("http://more-id-3"),
1070 GetSnippetWithUrl("http://more-id-4"), 947 GetSnippetWithUrl("http://more-id-4"),
1071 GetSnippetWithUrl("http://more-id-5"), 948 GetSnippetWithUrl("http://more-id-5"),
1072 GetSnippetWithUrl("http://more-id-6"), 949 GetSnippetWithUrl("http://more-id-6"),
1073 GetSnippetWithUrl("http://more-id-7"), 950 GetSnippetWithUrl("http://more-id-7"),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 // Workaround for gMock's lack of support for movable types. 985 // Workaround for gMock's lack of support for movable types.
1109 void SuggestionsLoaded( 986 void SuggestionsLoaded(
1110 MockFunction<void(Status, const std::vector<ContentSuggestion>&)>* loaded, 987 MockFunction<void(Status, const std::vector<ContentSuggestion>&)>* loaded,
1111 Status status, 988 Status status,
1112 std::vector<ContentSuggestion> suggestions) { 989 std::vector<ContentSuggestion> suggestions) {
1113 loaded->Call(status, suggestions); 990 loaded->Call(status, suggestions);
1114 } 991 }
1115 992
1116 } // namespace 993 } // namespace
1117 994
1118 TEST_F(RemoteSuggestionsProviderTest, ReturnFetchRequestEmptyBeforeInit) { 995 TEST_F(RemoteSuggestionsProviderImplTest, ReturnFetchRequestEmptyBeforeInit) {
1119 auto service = MakeSnippetsServiceWithoutInitialization(); 996 auto service = MakeSnippetsServiceWithoutInitialization();
1120 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded; 997 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded;
1121 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty())); 998 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty()));
1122 service->Fetch(articles_category(), std::set<std::string>(), 999 service->Fetch(articles_category(), std::set<std::string>(),
1123 base::Bind(&SuggestionsLoaded, &loaded)); 1000 base::Bind(&SuggestionsLoaded, &loaded));
1124 base::RunLoop().RunUntilIdle(); 1001 base::RunLoop().RunUntilIdle();
1125 } 1002 }
1126 1003
1127 TEST_F(RemoteSuggestionsProviderTest, ReturnTemporaryErrorForInvalidJson) { 1004 TEST_F(RemoteSuggestionsProviderImplTest, ReturnTemporaryErrorForInvalidJson) {
1128 auto service = MakeSnippetsService(); 1005 auto service = MakeSnippetsService();
1129 1006
1130 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded; 1007 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded;
1131 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty())); 1008 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty()));
1132 LoadMoreFromJSONString(service.get(), articles_category(), 1009 LoadMoreFromJSONString(service.get(), articles_category(),
1133 "invalid json string}]}", 1010 "invalid json string}]}",
1134 /*known_ids=*/std::set<std::string>(), 1011 /*known_ids=*/std::set<std::string>(),
1135 base::Bind(&SuggestionsLoaded, &loaded)); 1012 base::Bind(&SuggestionsLoaded, &loaded));
1136 EXPECT_THAT(service->snippets_fetcher()->last_status(), 1013 EXPECT_THAT(
1137 StartsWith("Received invalid JSON")); 1014 service->snippets_fetcher_for_testing_and_debugging()->last_status(),
1015 StartsWith("Received invalid JSON"));
1138 } 1016 }
1139 1017
1140 TEST_F(RemoteSuggestionsProviderTest, ReturnTemporaryErrorForInvalidSnippet) { 1018 TEST_F(RemoteSuggestionsProviderImplTest,
1019 ReturnTemporaryErrorForInvalidSnippet) {
1141 auto service = MakeSnippetsService(); 1020 auto service = MakeSnippetsService();
1142 1021
1143 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded; 1022 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded;
1144 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty())); 1023 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty()));
1145 LoadMoreFromJSONString(service.get(), articles_category(), 1024 LoadMoreFromJSONString(service.get(), articles_category(),
1146 GetTestJson({GetIncompleteSnippet()}), 1025 GetTestJson({GetIncompleteSnippet()}),
1147 /*known_ids=*/std::set<std::string>(), 1026 /*known_ids=*/std::set<std::string>(),
1148 base::Bind(&SuggestionsLoaded, &loaded)); 1027 base::Bind(&SuggestionsLoaded, &loaded));
1149 EXPECT_THAT(service->snippets_fetcher()->last_status(), 1028 EXPECT_THAT(
1150 StartsWith("Invalid / empty list")); 1029 service->snippets_fetcher_for_testing_and_debugging()->last_status(),
1030 StartsWith("Invalid / empty list"));
1151 } 1031 }
1152 1032
1153 TEST_F(RemoteSuggestionsProviderTest, ReturnTemporaryErrorForRequestFailure) { 1033 TEST_F(RemoteSuggestionsProviderImplTest,
1034 ReturnTemporaryErrorForRequestFailure) {
1154 // Created SnippetsService will fail by default with unsuccessful request. 1035 // Created SnippetsService will fail by default with unsuccessful request.
1155 auto service = MakeSnippetsService(/*set_empty_response=*/false); 1036 auto service = MakeSnippetsService(/*set_empty_response=*/false);
1156 1037
1157 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded; 1038 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded;
1158 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty())); 1039 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty()));
1159 service->Fetch(articles_category(), 1040 service->Fetch(articles_category(),
1160 /*known_ids=*/std::set<std::string>(), 1041 /*known_ids=*/std::set<std::string>(),
1161 base::Bind(&SuggestionsLoaded, &loaded)); 1042 base::Bind(&SuggestionsLoaded, &loaded));
1162 base::RunLoop().RunUntilIdle(); 1043 base::RunLoop().RunUntilIdle();
1163 } 1044 }
1164 1045
1165 TEST_F(RemoteSuggestionsProviderTest, ReturnTemporaryErrorForHttpFailure) { 1046 TEST_F(RemoteSuggestionsProviderImplTest, ReturnTemporaryErrorForHttpFailure) {
1166 auto service = MakeSnippetsService(); 1047 auto service = MakeSnippetsService();
1167 SetUpHttpError(); 1048 SetUpHttpError();
1168 1049
1169 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded; 1050 MockFunction<void(Status, const std::vector<ContentSuggestion>&)> loaded;
1170 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty())); 1051 EXPECT_CALL(loaded, Call(HasCode(StatusCode::TEMPORARY_ERROR), IsEmpty()));
1171 service->Fetch(articles_category(), 1052 service->Fetch(articles_category(),
1172 /*known_ids=*/std::set<std::string>(), 1053 /*known_ids=*/std::set<std::string>(),
1173 base::Bind(&SuggestionsLoaded, &loaded)); 1054 base::Bind(&SuggestionsLoaded, &loaded));
1174 base::RunLoop().RunUntilIdle(); 1055 base::RunLoop().RunUntilIdle();
1175 } 1056 }
1176 1057
1177 TEST_F(RemoteSuggestionsProviderTest, LoadInvalidJson) { 1058 TEST_F(RemoteSuggestionsProviderImplTest, LoadInvalidJson) {
1178 auto service = MakeSnippetsService(); 1059 auto service = MakeSnippetsService();
1179 1060
1180 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); 1061 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()}));
1181 EXPECT_THAT(service->snippets_fetcher()->last_status(), 1062 EXPECT_THAT(
1182 StartsWith("Received invalid JSON")); 1063 service->snippets_fetcher_for_testing_and_debugging()->last_status(),
1064 StartsWith("Received invalid JSON"));
1183 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1065 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1184 } 1066 }
1185 1067
1186 TEST_F(RemoteSuggestionsProviderTest, LoadInvalidJsonWithExistingSnippets) { 1068 TEST_F(RemoteSuggestionsProviderImplTest, LoadInvalidJsonWithExistingSnippets) {
1187 auto service = MakeSnippetsService(); 1069 auto service = MakeSnippetsService();
1188 1070
1189 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()})); 1071 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()}));
1190 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1072 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1191 ASSERT_EQ("OK", service->snippets_fetcher()->last_status()); 1073 ASSERT_EQ(
1074 "OK",
1075 service->snippets_fetcher_for_testing_and_debugging()->last_status());
1192 1076
1193 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); 1077 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()}));
1194 EXPECT_THAT(service->snippets_fetcher()->last_status(), 1078 EXPECT_THAT(
1195 StartsWith("Received invalid JSON")); 1079 service->snippets_fetcher_for_testing_and_debugging()->last_status(),
1080 StartsWith("Received invalid JSON"));
1196 // This should not have changed the existing snippets. 1081 // This should not have changed the existing snippets.
1197 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1082 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1198 } 1083 }
1199 1084
1200 TEST_F(RemoteSuggestionsProviderTest, LoadIncompleteJson) { 1085 TEST_F(RemoteSuggestionsProviderImplTest, LoadIncompleteJson) {
1201 auto service = MakeSnippetsService(); 1086 auto service = MakeSnippetsService();
1202 1087
1203 LoadFromJSONString(service.get(), GetTestJson({GetIncompleteSnippet()})); 1088 LoadFromJSONString(service.get(), GetTestJson({GetIncompleteSnippet()}));
1204 EXPECT_EQ("Invalid / empty list.", 1089 EXPECT_EQ(
1205 service->snippets_fetcher()->last_status()); 1090 "Invalid / empty list.",
1091 service->snippets_fetcher_for_testing_and_debugging()->last_status());
1206 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1092 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1207 } 1093 }
1208 1094
1209 TEST_F(RemoteSuggestionsProviderTest, LoadIncompleteJsonWithExistingSnippets) { 1095 TEST_F(RemoteSuggestionsProviderImplTest,
1096 LoadIncompleteJsonWithExistingSnippets) {
1210 auto service = MakeSnippetsService(); 1097 auto service = MakeSnippetsService();
1211 1098
1212 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()})); 1099 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()}));
1213 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1100 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1214 1101
1215 LoadFromJSONString(service.get(), GetTestJson({GetIncompleteSnippet()})); 1102 LoadFromJSONString(service.get(), GetTestJson({GetIncompleteSnippet()}));
1216 EXPECT_EQ("Invalid / empty list.", 1103 EXPECT_EQ(
1217 service->snippets_fetcher()->last_status()); 1104 "Invalid / empty list.",
1105 service->snippets_fetcher_for_testing_and_debugging()->last_status());
1218 // This should not have changed the existing snippets. 1106 // This should not have changed the existing snippets.
1219 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1107 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1220 } 1108 }
1221 1109
1222 TEST_F(RemoteSuggestionsProviderTest, Dismiss) { 1110 TEST_F(RemoteSuggestionsProviderImplTest, Dismiss) {
1223 auto service = MakeSnippetsService(); 1111 auto service = MakeSnippetsService();
1224 1112
1225 std::string json_str( 1113 std::string json_str(
1226 GetTestJson({GetSnippetWithSources("http://site.com", "Source 1", "")})); 1114 GetTestJson({GetSnippetWithSources("http://site.com", "Source 1", "")}));
1227 1115
1228 LoadFromJSONString(service.get(), json_str); 1116 LoadFromJSONString(service.get(), json_str);
1229 1117
1230 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1118 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1231 // Load the image to store it in the database. 1119 // Load the image to store it in the database.
1232 ServeImageCallback cb = 1120 ServeImageCallback cb =
(...skipping 30 matching lines...) Expand all
1263 LoadFromJSONString(service.get(), json_str); 1151 LoadFromJSONString(service.get(), json_str);
1264 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1152 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1265 1153
1266 // The snippet can be added again after clearing dismissed snippets. 1154 // The snippet can be added again after clearing dismissed snippets.
1267 service->ClearDismissedSuggestionsForDebugging(articles_category()); 1155 service->ClearDismissedSuggestionsForDebugging(articles_category());
1268 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1156 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1269 LoadFromJSONString(service.get(), json_str); 1157 LoadFromJSONString(service.get(), json_str);
1270 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1158 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1271 } 1159 }
1272 1160
1273 TEST_F(RemoteSuggestionsProviderTest, GetDismissed) { 1161 TEST_F(RemoteSuggestionsProviderImplTest, GetDismissed) {
1274 auto service = MakeSnippetsService(); 1162 auto service = MakeSnippetsService();
1275 1163
1276 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()})); 1164 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()}));
1277 1165
1278 service->DismissSuggestion(MakeArticleID(kSnippetUrl)); 1166 service->DismissSuggestion(MakeArticleID(kSnippetUrl));
1279 1167
1280 service->GetDismissedSuggestionsForDebugging( 1168 service->GetDismissedSuggestionsForDebugging(
1281 articles_category(), 1169 articles_category(),
1282 base::Bind( 1170 base::Bind(
1283 [](RemoteSuggestionsProvider* service, 1171 [](RemoteSuggestionsProviderImpl* service,
1284 RemoteSuggestionsProviderTest* test, 1172 RemoteSuggestionsProviderImplTest* test,
1285 std::vector<ContentSuggestion> dismissed_suggestions) { 1173 std::vector<ContentSuggestion> dismissed_suggestions) {
1286 EXPECT_EQ(1u, dismissed_suggestions.size()); 1174 EXPECT_EQ(1u, dismissed_suggestions.size());
1287 for (auto& suggestion : dismissed_suggestions) { 1175 for (auto& suggestion : dismissed_suggestions) {
1288 EXPECT_EQ(test->MakeArticleID(kSnippetUrl), suggestion.id()); 1176 EXPECT_EQ(test->MakeArticleID(kSnippetUrl), suggestion.id());
1289 } 1177 }
1290 }, 1178 },
1291 service.get(), this)); 1179 service.get(), this));
1292 base::RunLoop().RunUntilIdle(); 1180 base::RunLoop().RunUntilIdle();
1293 1181
1294 // There should be no dismissed snippet after clearing the list. 1182 // There should be no dismissed snippet after clearing the list.
1295 service->ClearDismissedSuggestionsForDebugging(articles_category()); 1183 service->ClearDismissedSuggestionsForDebugging(articles_category());
1296 service->GetDismissedSuggestionsForDebugging( 1184 service->GetDismissedSuggestionsForDebugging(
1297 articles_category(), 1185 articles_category(),
1298 base::Bind( 1186 base::Bind(
1299 [](RemoteSuggestionsProvider* service, 1187 [](RemoteSuggestionsProviderImpl* service,
1300 RemoteSuggestionsProviderTest* test, 1188 RemoteSuggestionsProviderImplTest* test,
1301 std::vector<ContentSuggestion> dismissed_suggestions) { 1189 std::vector<ContentSuggestion> dismissed_suggestions) {
1302 EXPECT_EQ(0u, dismissed_suggestions.size()); 1190 EXPECT_EQ(0u, dismissed_suggestions.size());
1303 }, 1191 },
1304 service.get(), this)); 1192 service.get(), this));
1305 base::RunLoop().RunUntilIdle(); 1193 base::RunLoop().RunUntilIdle();
1306 } 1194 }
1307 1195
1308 TEST_F(RemoteSuggestionsProviderTest, CreationTimestampParseFail) { 1196 TEST_F(RemoteSuggestionsProviderImplTest, CreationTimestampParseFail) {
1309 auto service = MakeSnippetsService(); 1197 auto service = MakeSnippetsService();
1310 1198
1311 std::string json = 1199 std::string json =
1312 GetSnippetWithTimes(GetDefaultCreationTime(), GetDefaultExpirationTime()); 1200 GetSnippetWithTimes(GetDefaultCreationTime(), GetDefaultExpirationTime());
1313 base::ReplaceFirstSubstringAfterOffset( 1201 base::ReplaceFirstSubstringAfterOffset(
1314 &json, 0, FormatTime(GetDefaultCreationTime()), "aaa1448459205"); 1202 &json, 0, FormatTime(GetDefaultCreationTime()), "aaa1448459205");
1315 std::string json_str(GetTestJson({json})); 1203 std::string json_str(GetTestJson({json}));
1316 1204
1317 LoadFromJSONString(service.get(), json_str); 1205 LoadFromJSONString(service.get(), json_str);
1318 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1206 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1319 } 1207 }
1320 1208
1321 TEST_F(RemoteSuggestionsProviderTest, RemoveExpiredDismissedContent) { 1209 TEST_F(RemoteSuggestionsProviderImplTest, RemoveExpiredDismissedContent) {
1322 auto service = MakeSnippetsService(); 1210 auto service = MakeSnippetsService();
1323 1211
1324 std::string json_str1(GetTestJson({GetExpiredSnippet()})); 1212 std::string json_str1(GetTestJson({GetExpiredSnippet()}));
1325 // Load it. 1213 // Load it.
1326 LoadFromJSONString(service.get(), json_str1); 1214 LoadFromJSONString(service.get(), json_str1);
1327 // Load the image to store it in the database. 1215 // Load the image to store it in the database.
1328 // TODO(tschumann): Introduce some abstraction to nicely work with image 1216 // TODO(tschumann): Introduce some abstraction to nicely work with image
1329 // fetching expectations. 1217 // fetching expectations.
1330 ServeImageCallback cb = 1218 ServeImageCallback cb =
1331 base::Bind(&ServeOneByOneImage, &service->GetImageFetcherForTesting()); 1219 base::Bind(&ServeOneByOneImage, &service->GetImageFetcherForTesting());
(...skipping 12 matching lines...) Expand all
1344 std::string json_str2(GetTestJson({GetSnippetWithUrl(kSnippetUrl2)})); 1232 std::string json_str2(GetTestJson({GetSnippetWithUrl(kSnippetUrl2)}));
1345 LoadFromJSONString(service.get(), json_str2); 1233 LoadFromJSONString(service.get(), json_str2);
1346 1234
1347 EXPECT_THAT(service->GetDismissedSnippetsForTesting(articles_category()), 1235 EXPECT_THAT(service->GetDismissedSnippetsForTesting(articles_category()),
1348 IsEmpty()); 1236 IsEmpty());
1349 1237
1350 // Verify the image got removed, too. 1238 // Verify the image got removed, too.
1351 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1239 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1352 } 1240 }
1353 1241
1354 TEST_F(RemoteSuggestionsProviderTest, ExpiredContentNotRemoved) { 1242 TEST_F(RemoteSuggestionsProviderImplTest, ExpiredContentNotRemoved) {
1355 auto service = MakeSnippetsService(); 1243 auto service = MakeSnippetsService();
1356 1244
1357 std::string json_str(GetTestJson({GetExpiredSnippet()})); 1245 std::string json_str(GetTestJson({GetExpiredSnippet()}));
1358 1246
1359 LoadFromJSONString(service.get(), json_str); 1247 LoadFromJSONString(service.get(), json_str);
1360 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1248 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1361 } 1249 }
1362 1250
1363 TEST_F(RemoteSuggestionsProviderTest, TestSingleSource) { 1251 TEST_F(RemoteSuggestionsProviderImplTest, TestSingleSource) {
1364 auto service = MakeSnippetsService(); 1252 auto service = MakeSnippetsService();
1365 1253
1366 std::string json_str(GetTestJson({GetSnippetWithSources( 1254 std::string json_str(GetTestJson({GetSnippetWithSources(
1367 "http://source1.com", "Source 1", "http://source1.amp.com")})); 1255 "http://source1.com", "Source 1", "http://source1.amp.com")}));
1368 1256
1369 LoadFromJSONString(service.get(), json_str); 1257 LoadFromJSONString(service.get(), json_str);
1370 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1258 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1371 const NTPSnippet& snippet = 1259 const NTPSnippet& snippet =
1372 *service->GetSnippetsForTesting(articles_category()).front(); 1260 *service->GetSnippetsForTesting(articles_category()).front();
1373 EXPECT_EQ(snippet.id(), kSnippetUrl); 1261 EXPECT_EQ(snippet.id(), kSnippetUrl);
1374 EXPECT_EQ(snippet.url(), GURL("http://source1.com")); 1262 EXPECT_EQ(snippet.url(), GURL("http://source1.com"));
1375 EXPECT_EQ(snippet.publisher_name(), std::string("Source 1")); 1263 EXPECT_EQ(snippet.publisher_name(), std::string("Source 1"));
1376 EXPECT_EQ(snippet.amp_url(), GURL("http://source1.amp.com")); 1264 EXPECT_EQ(snippet.amp_url(), GURL("http://source1.amp.com"));
1377 } 1265 }
1378 1266
1379 TEST_F(RemoteSuggestionsProviderTest, TestSingleSourceWithMalformedUrl) { 1267 TEST_F(RemoteSuggestionsProviderImplTest, TestSingleSourceWithMalformedUrl) {
1380 auto service = MakeSnippetsService(); 1268 auto service = MakeSnippetsService();
1381 1269
1382 std::string json_str(GetTestJson({GetSnippetWithSources( 1270 std::string json_str(GetTestJson({GetSnippetWithSources(
1383 "ceci n'est pas un url", "Source 1", "http://source1.amp.com")})); 1271 "ceci n'est pas un url", "Source 1", "http://source1.amp.com")}));
1384 1272
1385 LoadFromJSONString(service.get(), json_str); 1273 LoadFromJSONString(service.get(), json_str);
1386 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1274 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1387 } 1275 }
1388 1276
1389 TEST_F(RemoteSuggestionsProviderTest, TestSingleSourceWithMissingData) { 1277 TEST_F(RemoteSuggestionsProviderImplTest, TestSingleSourceWithMissingData) {
1390 auto service = MakeSnippetsService(); 1278 auto service = MakeSnippetsService();
1391 1279
1392 std::string json_str( 1280 std::string json_str(
1393 GetTestJson({GetSnippetWithSources("http://source1.com", "", "")})); 1281 GetTestJson({GetSnippetWithSources("http://source1.com", "", "")}));
1394 1282
1395 LoadFromJSONString(service.get(), json_str); 1283 LoadFromJSONString(service.get(), json_str);
1396 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1284 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1397 } 1285 }
1398 1286
1399 TEST_F(RemoteSuggestionsProviderTest, LogNumArticlesHistogram) { 1287 TEST_F(RemoteSuggestionsProviderImplTest, LogNumArticlesHistogram) {
1400 auto service = MakeSnippetsService(); 1288 auto service = MakeSnippetsService();
1401 1289
1402 base::HistogramTester tester; 1290 base::HistogramTester tester;
1403 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); 1291 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()}));
1404 1292
1405 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), 1293 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
1406 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); 1294 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1)));
1407 1295
1408 // Invalid JSON shouldn't contribute to NumArticlesFetched. 1296 // Invalid JSON shouldn't contribute to NumArticlesFetched.
1409 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), 1297 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"),
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1466 // But if there's a non-dismissed snippet in the database, recreating it 1354 // But if there's a non-dismissed snippet in the database, recreating it
1467 // shouldn't trigger a fetch. 1355 // shouldn't trigger a fetch.
1468 LoadFromJSONString( 1356 LoadFromJSONString(
1469 service.get(), 1357 service.get(),
1470 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")})); 1358 GetTestJson({GetSnippetWithUrl("http://not-dismissed.com")}));
1471 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1359 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1472 ResetSnippetsService(&service); 1360 ResetSnippetsService(&service);
1473 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6); 1361 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 6);
1474 } 1362 }
1475 1363
1476 TEST_F(RemoteSuggestionsProviderTest, DismissShouldRespectAllKnownUrls) { 1364 TEST_F(RemoteSuggestionsProviderImplTest, DismissShouldRespectAllKnownUrls) {
1477 auto service = MakeSnippetsService(); 1365 auto service = MakeSnippetsService();
1478 1366
1479 const base::Time creation = GetDefaultCreationTime(); 1367 const base::Time creation = GetDefaultCreationTime();
1480 const base::Time expiry = GetDefaultExpirationTime(); 1368 const base::Time expiry = GetDefaultExpirationTime();
1481 const std::vector<std::string> source_urls = { 1369 const std::vector<std::string> source_urls = {
1482 "http://mashable.com/2016/05/11/stolen", 1370 "http://mashable.com/2016/05/11/stolen",
1483 "http://www.aol.com/article/2016/05/stolen-doggie"}; 1371 "http://www.aol.com/article/2016/05/stolen-doggie"};
1484 const std::vector<std::string> publishers = {"Mashable", "AOL"}; 1372 const std::vector<std::string> publishers = {"Mashable", "AOL"};
1485 const std::vector<std::string> amp_urls = { 1373 const std::vector<std::string> amp_urls = {
1486 "http://mashable-amphtml.googleusercontent.com/1", 1374 "http://mashable-amphtml.googleusercontent.com/1",
(...skipping 10 matching lines...) Expand all
1497 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1385 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1498 1386
1499 // The same article from the AOL domain should now be detected as dismissed. 1387 // The same article from the AOL domain should now be detected as dismissed.
1500 LoadFromJSONString(service.get(), 1388 LoadFromJSONString(service.get(),
1501 GetTestJson({GetSnippetWithUrlAndTimesAndSource( 1389 GetTestJson({GetSnippetWithUrlAndTimesAndSource(
1502 source_urls, source_urls[1], creation, expiry, 1390 source_urls, source_urls[1], creation, expiry,
1503 publishers[1], amp_urls[1])})); 1391 publishers[1], amp_urls[1])}));
1504 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1392 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1505 } 1393 }
1506 1394
1507 TEST_F(RemoteSuggestionsProviderTest, StatusChanges) { 1395 TEST_F(RemoteSuggestionsProviderImplTest, StatusChanges) {
1508 auto service = MakeSnippetsService(); 1396 auto service = MakeSnippetsService();
1509 1397
1510 // Simulate user signed out 1398 // Simulate user signed out
1511 SetUpFetchResponse(GetTestJson({GetSnippet()})); 1399 SetUpFetchResponse(GetTestJson({GetSnippet()}));
1512 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, 1400 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN,
1513 RemoteSuggestionsStatus::SIGNED_OUT_AND_DISABLED); 1401 RemoteSuggestionsStatus::SIGNED_OUT_AND_DISABLED);
1514 1402
1515 base::RunLoop().RunUntilIdle(); 1403 base::RunLoop().RunUntilIdle();
1516 EXPECT_THAT(observer().StatusForCategory(articles_category()), 1404 EXPECT_THAT(observer().StatusForCategory(articles_category()),
1517 Eq(CategoryStatus::SIGNED_OUT)); 1405 Eq(CategoryStatus::SIGNED_OUT));
1518 EXPECT_THAT(RemoteSuggestionsProvider::State::DISABLED, Eq(service->state_)); 1406 EXPECT_THAT(RemoteSuggestionsProviderImpl::State::DISABLED,
1407 Eq(service->state_));
1519 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), 1408 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()),
1520 IsEmpty()); // No fetch should be made. 1409 IsEmpty()); // No fetch should be made.
1521 1410
1522 // Simulate user sign in. The service should be ready again and load snippets. 1411 // Simulate user sign in. The service should be ready again and load snippets.
1523 SetUpFetchResponse(GetTestJson({GetSnippet()})); 1412 SetUpFetchResponse(GetTestJson({GetSnippet()}));
1524 service->OnStatusChanged(RemoteSuggestionsStatus::SIGNED_OUT_AND_DISABLED, 1413 service->OnStatusChanged(RemoteSuggestionsStatus::SIGNED_OUT_AND_DISABLED,
1525 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN); 1414 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN);
1526 EXPECT_THAT(observer().StatusForCategory(articles_category()), 1415 EXPECT_THAT(observer().StatusForCategory(articles_category()),
1527 Eq(CategoryStatus::AVAILABLE_LOADING)); 1416 Eq(CategoryStatus::AVAILABLE_LOADING));
1528 1417
1529 base::RunLoop().RunUntilIdle(); 1418 base::RunLoop().RunUntilIdle();
1530 EXPECT_THAT(observer().StatusForCategory(articles_category()), 1419 EXPECT_THAT(observer().StatusForCategory(articles_category()),
1531 Eq(CategoryStatus::AVAILABLE)); 1420 Eq(CategoryStatus::AVAILABLE));
1532 EXPECT_THAT(RemoteSuggestionsProvider::State::READY, Eq(service->state_)); 1421 EXPECT_THAT(RemoteSuggestionsProviderImpl::State::READY, Eq(service->state_));
1533 EXPECT_FALSE(service->GetSnippetsForTesting(articles_category()).empty()); 1422 EXPECT_FALSE(service->GetSnippetsForTesting(articles_category()).empty());
1534 } 1423 }
1535 1424
1536 TEST_F(RemoteSuggestionsProviderTest, ImageReturnedWithTheSameId) { 1425 TEST_F(RemoteSuggestionsProviderImplTest, ImageReturnedWithTheSameId) {
1537 auto service = MakeSnippetsService(); 1426 auto service = MakeSnippetsService();
1538 1427
1539 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()})); 1428 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()}));
1540 1429
1541 gfx::Image image; 1430 gfx::Image image;
1542 MockFunction<void(const gfx::Image&)> image_fetched; 1431 MockFunction<void(const gfx::Image&)> image_fetched;
1543 ServeImageCallback cb = 1432 ServeImageCallback cb =
1544 base::Bind(&ServeOneByOneImage, &service->GetImageFetcherForTesting()); 1433 base::Bind(&ServeOneByOneImage, &service->GetImageFetcherForTesting());
1545 { 1434 {
1546 InSequence s; 1435 InSequence s;
1547 EXPECT_CALL(*image_fetcher(), StartOrQueueNetworkRequest(_, _, _)) 1436 EXPECT_CALL(*image_fetcher(), StartOrQueueNetworkRequest(_, _, _))
1548 .WillOnce(WithArgs<0, 2>(Invoke(&cb, &ServeImageCallback::Run))); 1437 .WillOnce(WithArgs<0, 2>(Invoke(&cb, &ServeImageCallback::Run)));
1549 EXPECT_CALL(image_fetched, Call(_)).WillOnce(SaveArg<0>(&image)); 1438 EXPECT_CALL(image_fetched, Call(_)).WillOnce(SaveArg<0>(&image));
1550 } 1439 }
1551 1440
1552 service->FetchSuggestionImage( 1441 service->FetchSuggestionImage(
1553 MakeArticleID(kSnippetUrl), 1442 MakeArticleID(kSnippetUrl),
1554 base::Bind(&MockFunction<void(const gfx::Image&)>::Call, 1443 base::Bind(&MockFunction<void(const gfx::Image&)>::Call,
1555 base::Unretained(&image_fetched))); 1444 base::Unretained(&image_fetched)));
1556 base::RunLoop().RunUntilIdle(); 1445 base::RunLoop().RunUntilIdle();
1557 // Check that the image by ServeOneByOneImage is really served. 1446 // Check that the image by ServeOneByOneImage is really served.
1558 EXPECT_EQ(1, image.Width()); 1447 EXPECT_EQ(1, image.Width());
1559 } 1448 }
1560 1449
1561 TEST_F(RemoteSuggestionsProviderTest, EmptyImageReturnedForNonExistentId) { 1450 TEST_F(RemoteSuggestionsProviderImplTest, EmptyImageReturnedForNonExistentId) {
1562 auto service = MakeSnippetsService(); 1451 auto service = MakeSnippetsService();
1563 1452
1564 // Create a non-empty image so that we can test the image gets updated. 1453 // Create a non-empty image so that we can test the image gets updated.
1565 gfx::Image image = gfx::test::CreateImage(1, 1); 1454 gfx::Image image = gfx::test::CreateImage(1, 1);
1566 MockFunction<void(const gfx::Image&)> image_fetched; 1455 MockFunction<void(const gfx::Image&)> image_fetched;
1567 EXPECT_CALL(image_fetched, Call(_)).WillOnce(SaveArg<0>(&image)); 1456 EXPECT_CALL(image_fetched, Call(_)).WillOnce(SaveArg<0>(&image));
1568 1457
1569 service->FetchSuggestionImage( 1458 service->FetchSuggestionImage(
1570 MakeArticleID(kSnippetUrl2), 1459 MakeArticleID(kSnippetUrl2),
1571 base::Bind(&MockFunction<void(const gfx::Image&)>::Call, 1460 base::Bind(&MockFunction<void(const gfx::Image&)>::Call,
1572 base::Unretained(&image_fetched))); 1461 base::Unretained(&image_fetched)));
1573 1462
1574 base::RunLoop().RunUntilIdle(); 1463 base::RunLoop().RunUntilIdle();
1575 EXPECT_TRUE(image.IsEmpty()); 1464 EXPECT_TRUE(image.IsEmpty());
1576 } 1465 }
1577 1466
1578 TEST_F(RemoteSuggestionsProviderTest, 1467 TEST_F(RemoteSuggestionsProviderImplTest,
1579 FetchingUnknownImageIdShouldNotHitDatabase) { 1468 FetchingUnknownImageIdShouldNotHitDatabase) {
1580 // Testing that the provider is not accessing the database is tricky. 1469 // Testing that the provider is not accessing the database is tricky.
1581 // Therefore, we simply put in some data making sure that if the provider asks 1470 // Therefore, we simply put in some data making sure that if the provider asks
1582 // the database, it will get a wrong answer. 1471 // the database, it will get a wrong answer.
1583 auto service = MakeSnippetsService(); 1472 auto service = MakeSnippetsService();
1584 1473
1585 ContentSuggestion::ID unknown_id = MakeArticleID(kSnippetUrl2); 1474 ContentSuggestion::ID unknown_id = MakeArticleID(kSnippetUrl2);
1586 database()->SaveImage(unknown_id.id_within_category(), "some image blob"); 1475 database()->SaveImage(unknown_id.id_within_category(), "some image blob");
1587 // Set up the image decoder to always return the 1x1 test image. 1476 // Set up the image decoder to always return the 1x1 test image.
1588 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1)); 1477 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1));
1589 1478
1590 // Create a non-empty image so that we can test the image gets updated. 1479 // Create a non-empty image so that we can test the image gets updated.
1591 gfx::Image image = gfx::test::CreateImage(2, 2); 1480 gfx::Image image = gfx::test::CreateImage(2, 2);
1592 MockFunction<void(const gfx::Image&)> image_fetched; 1481 MockFunction<void(const gfx::Image&)> image_fetched;
1593 EXPECT_CALL(image_fetched, Call(_)).WillOnce(SaveArg<0>(&image)); 1482 EXPECT_CALL(image_fetched, Call(_)).WillOnce(SaveArg<0>(&image));
1594 1483
1595 service->FetchSuggestionImage( 1484 service->FetchSuggestionImage(
1596 MakeArticleID(kSnippetUrl2), 1485 MakeArticleID(kSnippetUrl2),
1597 base::Bind(&MockFunction<void(const gfx::Image&)>::Call, 1486 base::Bind(&MockFunction<void(const gfx::Image&)>::Call,
1598 base::Unretained(&image_fetched))); 1487 base::Unretained(&image_fetched)));
1599 1488
1600 base::RunLoop().RunUntilIdle(); 1489 base::RunLoop().RunUntilIdle();
1601 EXPECT_TRUE(image.IsEmpty()) << "got image with width: " << image.Width(); 1490 EXPECT_TRUE(image.IsEmpty()) << "got image with width: " << image.Width();
1602 } 1491 }
1603 1492
1604 TEST_F(RemoteSuggestionsProviderTest, ClearHistoryRemovesAllSuggestions) { 1493 TEST_F(RemoteSuggestionsProviderImplTest, ClearHistoryRemovesAllSuggestions) {
1605 auto service = MakeSnippetsService(); 1494 auto service = MakeSnippetsService();
1606 1495
1607 std::string first_snippet = GetSnippetWithUrl("http://url1.com"); 1496 std::string first_snippet = GetSnippetWithUrl("http://url1.com");
1608 std::string second_snippet = GetSnippetWithUrl("http://url2.com"); 1497 std::string second_snippet = GetSnippetWithUrl("http://url2.com");
1609 std::string json_str = GetTestJson({first_snippet, second_snippet}); 1498 std::string json_str = GetTestJson({first_snippet, second_snippet});
1610 LoadFromJSONString(service.get(), json_str); 1499 LoadFromJSONString(service.get(), json_str);
1611 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(2)); 1500 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(2));
1612 1501
1613 service->DismissSuggestion(MakeArticleID("http://url1.com")); 1502 service->DismissSuggestion(MakeArticleID("http://url1.com"));
1614 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1503 ASSERT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1615 ASSERT_THAT(service->GetDismissedSnippetsForTesting(articles_category()), 1504 ASSERT_THAT(service->GetDismissedSnippetsForTesting(articles_category()),
1616 SizeIs(1)); 1505 SizeIs(1));
1617 1506
1618 base::Time begin = base::Time::FromTimeT(123), 1507 base::Time begin = base::Time::FromTimeT(123),
1619 end = base::Time::FromTimeT(456); 1508 end = base::Time::FromTimeT(456);
1620 base::Callback<bool(const GURL& url)> filter; 1509 base::Callback<bool(const GURL& url)> filter;
1621 service->ClearHistory(begin, end, filter); 1510 service->ClearHistory(begin, end, filter);
1622 1511
1623 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1512 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1624 EXPECT_THAT(service->GetDismissedSnippetsForTesting(articles_category()), 1513 EXPECT_THAT(service->GetDismissedSnippetsForTesting(articles_category()),
1625 IsEmpty()); 1514 IsEmpty());
1626 } 1515 }
1627 1516
1628 TEST_F(RemoteSuggestionsProviderTest, SuggestionsFetchedOnSignInAndSignOut) { 1517 TEST_F(RemoteSuggestionsProviderImplTest,
1518 SuggestionsFetchedOnSignInAndSignOut) {
1629 auto service = MakeSnippetsService(); 1519 auto service = MakeSnippetsService();
1630 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); 1520 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty());
1631 1521
1632 // |MakeSnippetsService()| creates a service where user is signed in already, 1522 // |MakeSnippetsService()| creates a service where user is signed in already,
1633 // so we start by signing out. 1523 // so we start by signing out.
1634 SetUpFetchResponse(GetTestJson({GetSnippetN(1)})); 1524 SetUpFetchResponse(GetTestJson({GetSnippetN(1)}));
1635 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, 1525 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN,
1636 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT); 1526 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT);
1637 base::RunLoop().RunUntilIdle(); 1527 base::RunLoop().RunUntilIdle();
1638 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1)); 1528 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(1));
1639 1529
1640 // Sign in to check a transition from signed out to signed in. 1530 // Sign in to check a transition from signed out to signed in.
1641 SetUpFetchResponse(GetTestJson({GetSnippetN(1), GetSnippetN(2)})); 1531 SetUpFetchResponse(GetTestJson({GetSnippetN(1), GetSnippetN(2)}));
1642 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT, 1532 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT,
1643 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN); 1533 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN);
1644 base::RunLoop().RunUntilIdle(); 1534 base::RunLoop().RunUntilIdle();
1645 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(2)); 1535 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), SizeIs(2));
1646 } 1536 }
1647 1537
1648 TEST_F(RemoteSuggestionsProviderTest, ShouldClearOrphanedImagesOnRestart) { 1538 TEST_F(RemoteSuggestionsProviderImplTest, ShouldClearOrphanedImagesOnRestart) {
1649 auto service = MakeSnippetsService(); 1539 auto service = MakeSnippetsService();
1650 1540
1651 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()})); 1541 LoadFromJSONString(service.get(), GetTestJson({GetSnippet()}));
1652 ServeImageCallback cb = 1542 ServeImageCallback cb =
1653 base::Bind(&ServeOneByOneImage, &service->GetImageFetcherForTesting()); 1543 base::Bind(&ServeOneByOneImage, &service->GetImageFetcherForTesting());
1654 1544
1655 EXPECT_CALL(*image_fetcher(), StartOrQueueNetworkRequest(_, _, _)) 1545 EXPECT_CALL(*image_fetcher(), StartOrQueueNetworkRequest(_, _, _))
1656 .WillOnce(WithArgs<0, 2>(Invoke(&cb, &ServeImageCallback::Run))); 1546 .WillOnce(WithArgs<0, 2>(Invoke(&cb, &ServeImageCallback::Run)));
1657 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1)); 1547 image_decoder()->SetDecodedImage(gfx::test::CreateImage(1, 1));
1658 1548
1659 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl)); 1549 gfx::Image image = FetchImage(service.get(), MakeArticleID(kSnippetUrl));
1660 EXPECT_EQ(1, image.Width()); 1550 EXPECT_EQ(1, image.Width());
1661 EXPECT_FALSE(image.IsEmpty()); 1551 EXPECT_FALSE(image.IsEmpty());
1662 1552
1663 // Send new suggestion which don't include the snippet referencing the image. 1553 // Send new suggestion which don't include the snippet referencing the image.
1664 LoadFromJSONString(service.get(), 1554 LoadFromJSONString(service.get(),
1665 GetTestJson({GetSnippetWithUrl( 1555 GetTestJson({GetSnippetWithUrl(
1666 "http://something.com/pletely/unrelated")})); 1556 "http://something.com/pletely/unrelated")}));
1667 // The image should still be available until a restart happens. 1557 // The image should still be available until a restart happens.
1668 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1558 EXPECT_FALSE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1669 ResetSnippetsService(&service); 1559 ResetSnippetsService(&service);
1670 // After the restart, the image should be garbage collected. 1560 // After the restart, the image should be garbage collected.
1671 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty()); 1561 EXPECT_TRUE(FetchImage(service.get(), MakeArticleID(kSnippetUrl)).IsEmpty());
1672 } 1562 }
1673 1563
1674 TEST_F(RemoteSuggestionsProviderTest, 1564 TEST_F(RemoteSuggestionsProviderImplTest,
1675 ShouldHandleMoreThanMaxSnippetsInResponse) { 1565 ShouldHandleMoreThanMaxSnippetsInResponse) {
1676 auto service = MakeSnippetsService(); 1566 auto service = MakeSnippetsService();
1677 1567
1678 std::vector<std::string> suggestions; 1568 std::vector<std::string> suggestions;
1679 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) { 1569 for (int i = 0; i < service->GetMaxSnippetCountForTesting() + 1; ++i) {
1680 suggestions.push_back(GetSnippetWithUrl( 1570 suggestions.push_back(GetSnippetWithUrl(
1681 base::StringPrintf("http://localhost/snippet-id-%d", i))); 1571 base::StringPrintf("http://localhost/snippet-id-%d", i)));
1682 } 1572 }
1683 LoadFromJSONString(service.get(), GetTestJson(suggestions)); 1573 LoadFromJSONString(service.get(), GetTestJson(suggestions));
1684 // TODO(tschumann): We should probably trim out any additional results and 1574 // TODO(tschumann): We should probably trim out any additional results and
1685 // only serve the MaxSnippetCount items. 1575 // only serve the MaxSnippetCount items.
1686 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), 1576 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()),
1687 SizeIs(service->GetMaxSnippetCountForTesting() + 1)); 1577 SizeIs(service->GetMaxSnippetCountForTesting() + 1));
1688 } 1578 }
1689 1579
1690 TEST_F(RemoteSuggestionsProviderTest, StoreLastSuccessfullBackgroundFetchTime) { 1580 TEST_F(RemoteSuggestionsProviderImplTest,
1691 // On initialization of the RemoteSuggestionsProvider a background fetch is 1581 StoreLastSuccessfullBackgroundFetchTime) {
1582 // On initialization of the RemoteSuggestionsProviderImpl a background fetch
1583 // is
Marc Treib 2016/12/19 12:59:23 nit: "wrong" line break
jkrcal 2016/12/20 16:39:46 Done.
1692 // triggered since the snippets DB is empty. Therefore the service must not be 1584 // triggered since the snippets DB is empty. Therefore the service must not be
1693 // initialized until the test clock is set. 1585 // initialized until the test clock is set.
1694 auto service = MakeSnippetsServiceWithoutInitialization(); 1586 auto service = MakeSnippetsServiceWithoutInitialization();
1695 1587
1696 auto simple_test_clock = base::MakeUnique<base::SimpleTestClock>(); 1588 auto simple_test_clock = base::MakeUnique<base::SimpleTestClock>();
1697 base::SimpleTestClock* simple_test_clock_ptr = simple_test_clock.get(); 1589 base::SimpleTestClock* simple_test_clock_ptr = simple_test_clock.get();
1698 service->SetClockForTesting(std::move(simple_test_clock)); 1590 service->SetClockForTesting(std::move(simple_test_clock));
1699 1591
1700 // Test that the preference is correctly initialized with the default value 0. 1592 // Test that the preference is correctly initialized with the default value 0.
1701 EXPECT_EQ( 1593 EXPECT_EQ(
1702 0, pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); 1594 0, pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
1703 1595
1704 WaitForSnippetsServiceInitialization(service.get(), 1596 WaitForSnippetsServiceInitialization(service.get(),
1705 /*set_empty_response=*/true); 1597 /*set_empty_response=*/true);
1706 EXPECT_EQ( 1598 EXPECT_EQ(
1707 simple_test_clock_ptr->Now().ToInternalValue(), 1599 simple_test_clock_ptr->Now().ToInternalValue(),
1708 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); 1600 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
1709 1601
1710 // Advance the time and check whether the time was updated correctly after the 1602 // Advance the time and check whether the time was updated correctly after the
1711 // background fetch. 1603 // background fetch.
1712 simple_test_clock_ptr->Advance(TimeDelta::FromHours(1)); 1604 simple_test_clock_ptr->Advance(TimeDelta::FromHours(1));
1713 service->FetchSnippetsInTheBackground(); 1605 // TODO(jkrcal): Move together with the pref storage into the scheduler.
1606 static_cast<RemoteSuggestionsScheduler::Updater*>(service.get())
1607 ->UpdateRemoteSuggestionsBySchedule();
1714 base::RunLoop().RunUntilIdle(); 1608 base::RunLoop().RunUntilIdle();
1715 EXPECT_EQ( 1609 EXPECT_EQ(
1716 simple_test_clock_ptr->Now().ToInternalValue(), 1610 simple_test_clock_ptr->Now().ToInternalValue(),
1717 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime)); 1611 pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
1718 // TODO(markusheintz): Add a test that simulates a browser restart once the 1612 // TODO(markusheintz): Add a test that simulates a browser restart once the
1719 // scheduler refactoring is done (crbug.com/672434). 1613 // scheduler refactoring is done (crbug.com/672434).
1720 } 1614 }
1721 1615
1616 TEST_F(RemoteSuggestionsProviderImplTest, CallsProviderActiveCallbackIfReady) {
1617 // Initiate the service so that it is already READY.
1618 auto service = MakeSnippetsService();
1619
1620 MockFunction<void(bool)> activeness_observer;
1621 // The callback should be called on registering.
1622 EXPECT_CALL(activeness_observer, Call(true));
1623 service->RegisterActivenessObserver(activeness_observer);
1624 }
1625
1626 TEST_F(RemoteSuggestionsProviderImplTest,
1627 DoesNotCallProviderActiveCallbackIfNotInited) {
1628 auto service = MakeSnippetsServiceWithoutInitialization();
1629
1630 MockFunction<void(bool)> activeness_observer;
1631 // The provider is not initialized yet, no callback should be called on
1632 // registering.
1633 EXPECT_CALL(activeness_observer, Call(_)).Times(0);
tschumann 2016/12/19 11:07:19 this is a bit backwards. Instead, I'd recommend a
Marc Treib 2016/12/19 12:59:23 The ".Times(0)" pattern is somewhat common, though
jkrcal 2016/12/20 16:39:46 Agreed, I've added it into the testing agenda for
jkrcal 2016/12/20 16:39:46 Done.
1634 service->RegisterActivenessObserver(activeness_observer);
1635 }
1636
1637 TEST_F(RemoteSuggestionsProviderImplTest,
1638 CallsProviderActiveCallbackWhenReady) {
1639 auto service = MakeSnippetsServiceWithoutInitialization();
1640 MockFunction<void(bool)> activeness_observer;
1641 service->RegisterActivenessObserver(activeness_observer);
1642
1643 // Call the callback when becoming ready.
tschumann 2016/12/19 11:07:19 nit: The comment being written in "active" form is
jkrcal 2016/12/20 16:39:46 Done.
1644 EXPECT_CALL(activeness_observer, Call(true));
1645 EnterState(State::READY);
1646 }
1647
1648 TEST_F(RemoteSuggestionsProviderImplTest, CallsProviderActiveCallbackOnError) {
1649 auto service = MakeSnippetsServiceWithoutInitialization();
1650 MockFunction<void(bool)> activeness_observer;
1651 service->RegisterActivenessObserver(activeness_observer);
1652
1653 // Call the callback on error.
1654 EXPECT_CALL(activeness_observer, Call(false));
1655 EnterState(State::ERROR);
1656 }
1657
1658 TEST_F(RemoteSuggestionsProviderImplTest,
1659 CallsProviderActiveCallbackWhenDisabled) {
1660 auto service = MakeSnippetsServiceWithoutInitialization();
1661 MockFunction<void(bool)> activeness_observer;
1662 service->RegisterActivenessObserver(activeness_observer);
1663
1664 // Call the callback when becoming disabled.
1665 EXPECT_CALL(activeness_observer, Call(false));
1666 EnterState(State::DISABLED);
1667 }
1668
1722 } // namespace ntp_snippets 1669 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698