OLD | NEW |
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/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/remote/ntp_snippets_service.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 public: | 381 public: |
382 NTPSnippetsServiceTest() | 382 NTPSnippetsServiceTest() |
383 : params_manager_(ntp_snippets::kStudyName, | 383 : params_manager_(ntp_snippets::kStudyName, |
384 {{"content_suggestions_backend", | 384 {{"content_suggestions_backend", |
385 kTestContentSuggestionsServerEndpoint}}), | 385 kTestContentSuggestionsServerEndpoint}}), |
386 fake_url_fetcher_factory_( | 386 fake_url_fetcher_factory_( |
387 /*default_factory=*/&failing_url_fetcher_factory_), | 387 /*default_factory=*/&failing_url_fetcher_factory_), |
388 test_url_(kTestContentSuggestionsServerWithAPIKey), | 388 test_url_(kTestContentSuggestionsServerWithAPIKey), |
389 user_classifier_(/*pref_service=*/nullptr), | 389 user_classifier_(/*pref_service=*/nullptr), |
390 image_fetcher_(nullptr), | 390 image_fetcher_(nullptr), |
391 image_decoder_(nullptr) { | 391 image_decoder_(nullptr), |
| 392 caller_() { |
392 NTPSnippetsService::RegisterProfilePrefs(utils_.pref_service()->registry()); | 393 NTPSnippetsService::RegisterProfilePrefs(utils_.pref_service()->registry()); |
393 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); | 394 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); |
394 | 395 |
395 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); | 396 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); |
396 } | 397 } |
397 | 398 |
398 ~NTPSnippetsServiceTest() override { | 399 ~NTPSnippetsServiceTest() override { |
399 // We need to run the message loop after deleting the database, because | 400 // We need to run the message loop after deleting the database, because |
400 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task | 401 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task |
401 // runner. Without this, we'd get reports of memory leaks. | 402 // runner. Without this, we'd get reports of memory leaks. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 net::URLRequestStatus::SUCCESS); | 497 net::URLRequestStatus::SUCCESS); |
497 } | 498 } |
498 | 499 |
499 void LoadFromJSONString(NTPSnippetsService* service, | 500 void LoadFromJSONString(NTPSnippetsService* service, |
500 const std::string& json) { | 501 const std::string& json) { |
501 SetUpFetchResponse(json); | 502 SetUpFetchResponse(json); |
502 service->FetchSnippets(true); | 503 service->FetchSnippets(true); |
503 base::RunLoop().RunUntilIdle(); | 504 base::RunLoop().RunUntilIdle(); |
504 } | 505 } |
505 | 506 |
| 507 void LoadMoreFromJSONString(NTPSnippetsService* service, |
| 508 const Category& category, |
| 509 const std::string& json, |
| 510 const std::set<std::string>& known_ids, |
| 511 NTPSnippetsService::FetchingCallback callback) { |
| 512 SetUpFetchResponse(json); |
| 513 service->Fetch(category, known_ids, callback); |
| 514 base::RunLoop().RunUntilIdle(); |
| 515 } |
| 516 |
506 private: | 517 private: |
| 518 class MockCaller { |
| 519 public: |
| 520 void EmptyCallback(std::vector<ContentSuggestion>) {} |
| 521 void CheckCallback(std::vector<ContentSuggestion> v) { MustCallback(); } |
| 522 MOCK_METHOD0(MustCallback, void()); |
| 523 }; |
| 524 |
507 variations::testing::VariationParamsManager params_manager_; | 525 variations::testing::VariationParamsManager params_manager_; |
508 test::NTPSnippetsTestUtils utils_; | 526 test::NTPSnippetsTestUtils utils_; |
509 base::MessageLoop message_loop_; | 527 base::MessageLoop message_loop_; |
510 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; | 528 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; |
511 // Instantiation of factory automatically sets itself as URLFetcher's factory. | 529 // Instantiation of factory automatically sets itself as URLFetcher's factory. |
512 net::FakeURLFetcherFactory fake_url_fetcher_factory_; | 530 net::FakeURLFetcherFactory fake_url_fetcher_factory_; |
513 const GURL test_url_; | 531 const GURL test_url_; |
514 std::unique_ptr<OAuth2TokenService> fake_token_service_; | 532 std::unique_ptr<OAuth2TokenService> fake_token_service_; |
515 UserClassifier user_classifier_; | 533 UserClassifier user_classifier_; |
516 NiceMock<MockScheduler> scheduler_; | 534 NiceMock<MockScheduler> scheduler_; |
517 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; | 535 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; |
518 CategoryFactory category_factory_; | 536 CategoryFactory category_factory_; |
519 NiceMock<MockImageFetcher>* image_fetcher_; | 537 NiceMock<MockImageFetcher>* image_fetcher_; |
520 FakeImageDecoder* image_decoder_; | 538 FakeImageDecoder* image_decoder_; |
521 | 539 |
522 base::ScopedTempDir database_dir_; | 540 base::ScopedTempDir database_dir_; |
| 541 MockCaller caller_; |
523 | 542 |
524 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); | 543 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); |
525 }; | 544 }; |
526 | 545 |
527 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) { | 546 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) { |
528 // We should get two |Schedule| calls: The first when initialization | 547 // We should get two |Schedule| calls: The first when initialization |
529 // completes, the second one after the automatic (since the service doesn't | 548 // completes, the second one after the automatic (since the service doesn't |
530 // have any data yet) fetch finishes. | 549 // have any data yet) fetch finishes. |
531 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2); | 550 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2); |
532 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); | 551 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), | 844 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
826 ElementsAre(IdEq(first))); | 845 ElementsAre(IdEq(first))); |
827 | 846 |
828 std::string second("http://second"); | 847 std::string second("http://second"); |
829 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(second)})); | 848 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(second)})); |
830 // The snippets loaded last replace all that was loaded previously. | 849 // The snippets loaded last replace all that was loaded previously. |
831 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), | 850 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
832 ElementsAre(IdEq(second))); | 851 ElementsAre(IdEq(second))); |
833 } | 852 } |
834 | 853 |
| 854 TEST_F(NTPSnippetsServiceTest, LoadsAdditionalSnippets) { |
| 855 auto service = MakeSnippetsService(); |
| 856 |
| 857 std::string first("http://first"); |
| 858 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(first)})); |
| 859 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
| 860 ElementsAre(IdEq(first))); |
| 861 |
| 862 std::string second("http://second"); |
| 863 LoadMoreFromJSONString(service.get(), |
| 864 articles_category(), |
| 865 GetTestJson({GetSnippetWithUrl(second)}), |
| 866 std::set<std::string>(), |
| 867 base::Bind([](std::vector<ContentSuggestion>) {})); |
| 868 // The snippets loaded last are added to the previously loaded. |
| 869 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
| 870 ElementsAre(IdEq(first), IdEq(second))); |
| 871 } |
| 872 |
| 873 namespace { |
| 874 |
| 875 // Workaround for gMock's lack of support for movable types. |
| 876 void SuggestionsLoaded( |
| 877 MockFunction<void(const std::vector<ContentSuggestion>& v)>* loaded, |
| 878 std::vector<ContentSuggestion> v) { |
| 879 loaded->Call(v); |
| 880 } |
| 881 |
| 882 } // namespace |
| 883 |
| 884 TEST_F(NTPSnippetsServiceTest, InvokesOnlyCallbackOnFetchingMore) { |
| 885 auto service = MakeSnippetsService(); |
| 886 |
| 887 MockFunction<void(const std::vector<ContentSuggestion>&)> loaded; |
| 888 EXPECT_CALL(loaded, Call(SizeIs(1))); |
| 889 |
| 890 LoadMoreFromJSONString(service.get(), articles_category(), |
| 891 GetTestJson({GetSnippetWithUrl("http://some")}), |
| 892 std::set<std::string>(), |
| 893 base::Bind(&SuggestionsLoaded, &loaded)); |
| 894 |
| 895 // The observer shouldn't have been triggered. |
| 896 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), |
| 897 IsEmpty()); |
| 898 } |
| 899 |
| 900 TEST_F(NTPSnippetsServiceTest, ReturnFetchRequestEmptyBeforeInit) { |
| 901 auto service = MakeSnippetsServiceWithoutInitialization(); |
| 902 MockFunction<void(const std::vector<ContentSuggestion>&)> loaded; |
| 903 EXPECT_CALL(loaded, Call(SizeIs(0))); |
| 904 service->Fetch(articles_category(), std::set<std::string>(), |
| 905 base::Bind(&SuggestionsLoaded, &loaded)); |
| 906 base::RunLoop().RunUntilIdle(); |
| 907 } |
| 908 |
835 TEST_F(NTPSnippetsServiceTest, LoadInvalidJson) { | 909 TEST_F(NTPSnippetsServiceTest, LoadInvalidJson) { |
836 auto service = MakeSnippetsService(); | 910 auto service = MakeSnippetsService(); |
837 | 911 |
838 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); | 912 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); |
839 EXPECT_THAT(service->snippets_fetcher()->last_status(), | 913 EXPECT_THAT(service->snippets_fetcher()->last_status(), |
840 StartsWith("Received invalid JSON")); | 914 StartsWith("Received invalid JSON")); |
841 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); | 915 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); |
842 } | 916 } |
843 | 917 |
844 TEST_F(NTPSnippetsServiceTest, LoadInvalidJsonWithExistingSnippets) { | 918 TEST_F(NTPSnippetsServiceTest, LoadInvalidJsonWithExistingSnippets) { |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 base::StringPrintf("http://localhost/snippet-id-%d", i))); | 1370 base::StringPrintf("http://localhost/snippet-id-%d", i))); |
1297 } | 1371 } |
1298 LoadFromJSONString(service.get(), GetTestJson(suggestions)); | 1372 LoadFromJSONString(service.get(), GetTestJson(suggestions)); |
1299 // TODO(tschumann): We should probably trim out any additional results and | 1373 // TODO(tschumann): We should probably trim out any additional results and |
1300 // only serve the MaxSnippetCount items. | 1374 // only serve the MaxSnippetCount items. |
1301 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), | 1375 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
1302 SizeIs(service->GetMaxSnippetCountForTesting() + 1)); | 1376 SizeIs(service->GetMaxSnippetCountForTesting() + 1)); |
1303 } | 1377 } |
1304 | 1378 |
1305 } // namespace ntp_snippets | 1379 } // namespace ntp_snippets |
OLD | NEW |