Chromium Code Reviews| 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 std::string& json, | |
| 509 const std::set<std::string>& known_ids, | |
| 510 NTPSnippetsService::FetchingCallback callback) { | |
| 511 SetUpFetchResponse(json); | |
| 512 service->Fetch(articles_category(), known_ids, callback); | |
|
markusheintz_
2016/11/03 11:43:54
nit: It would be nice to pass in the articles_cate
tschumann
2016/11/03 11:55:46
very valid point. done.
| |
| 513 base::RunLoop().RunUntilIdle(); | |
| 514 } | |
| 515 | |
| 506 private: | 516 private: |
| 517 class MockCaller { | |
| 518 public: | |
| 519 void EmptyCallback(std::vector<ContentSuggestion>) {} | |
| 520 void CheckCallback(std::vector<ContentSuggestion> v) { MustCallback(); } | |
| 521 MOCK_METHOD0(MustCallback, void()); | |
| 522 }; | |
| 523 | |
| 507 variations::testing::VariationParamsManager params_manager_; | 524 variations::testing::VariationParamsManager params_manager_; |
| 508 test::NTPSnippetsTestUtils utils_; | 525 test::NTPSnippetsTestUtils utils_; |
| 509 base::MessageLoop message_loop_; | 526 base::MessageLoop message_loop_; |
| 510 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; | 527 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; |
| 511 // Instantiation of factory automatically sets itself as URLFetcher's factory. | 528 // Instantiation of factory automatically sets itself as URLFetcher's factory. |
| 512 net::FakeURLFetcherFactory fake_url_fetcher_factory_; | 529 net::FakeURLFetcherFactory fake_url_fetcher_factory_; |
| 513 const GURL test_url_; | 530 const GURL test_url_; |
| 514 std::unique_ptr<OAuth2TokenService> fake_token_service_; | 531 std::unique_ptr<OAuth2TokenService> fake_token_service_; |
| 515 UserClassifier user_classifier_; | 532 UserClassifier user_classifier_; |
| 516 NiceMock<MockScheduler> scheduler_; | 533 NiceMock<MockScheduler> scheduler_; |
| 517 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; | 534 std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_; |
| 518 CategoryFactory category_factory_; | 535 CategoryFactory category_factory_; |
| 519 NiceMock<MockImageFetcher>* image_fetcher_; | 536 NiceMock<MockImageFetcher>* image_fetcher_; |
| 520 FakeImageDecoder* image_decoder_; | 537 FakeImageDecoder* image_decoder_; |
| 521 | 538 |
| 522 base::ScopedTempDir database_dir_; | 539 base::ScopedTempDir database_dir_; |
| 540 MockCaller caller_; | |
| 523 | 541 |
| 524 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); | 542 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); |
| 525 }; | 543 }; |
| 526 | 544 |
| 527 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) { | 545 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) { |
| 528 // We should get two |Schedule| calls: The first when initialization | 546 // We should get two |Schedule| calls: The first when initialization |
| 529 // completes, the second one after the automatic (since the service doesn't | 547 // completes, the second one after the automatic (since the service doesn't |
| 530 // have any data yet) fetch finishes. | 548 // have any data yet) fetch finishes. |
| 531 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2); | 549 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(2); |
| 532 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); | 550 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()), | 843 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
| 826 ElementsAre(IdEq(first))); | 844 ElementsAre(IdEq(first))); |
| 827 | 845 |
| 828 std::string second("http://second"); | 846 std::string second("http://second"); |
| 829 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(second)})); | 847 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(second)})); |
| 830 // The snippets loaded last replace all that was loaded previously. | 848 // The snippets loaded last replace all that was loaded previously. |
| 831 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), | 849 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
| 832 ElementsAre(IdEq(second))); | 850 ElementsAre(IdEq(second))); |
| 833 } | 851 } |
| 834 | 852 |
| 853 TEST_F(NTPSnippetsServiceTest, LoadsAdditionalSnippets) { | |
| 854 auto service = MakeSnippetsService(); | |
| 855 | |
| 856 std::string first("http://first"); | |
| 857 LoadFromJSONString(service.get(), GetTestJson({GetSnippetWithUrl(first)})); | |
| 858 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), | |
| 859 ElementsAre(IdEq(first))); | |
| 860 | |
| 861 std::string second("http://second"); | |
| 862 LoadMoreFromJSONString(service.get(), | |
| 863 GetTestJson({GetSnippetWithUrl(second)}), | |
| 864 std::set<std::string>(), | |
| 865 base::Bind([](std::vector<ContentSuggestion>) {})); | |
| 866 // The snippets loaded last are added to the previously loaded. | |
| 867 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), | |
| 868 ElementsAre(IdEq(first), IdEq(second))); | |
| 869 } | |
| 870 | |
| 871 namespace { | |
| 872 | |
| 873 // Workaround for gMock's lack of support for movable types. | |
| 874 void SuggestionsLoaded( | |
| 875 MockFunction<void(const std::vector<ContentSuggestion>& v)>* loaded, | |
| 876 std::vector<ContentSuggestion> v) { | |
| 877 loaded->Call(v); | |
| 878 } | |
| 879 | |
| 880 } // namespace | |
| 881 | |
| 882 TEST_F(NTPSnippetsServiceTest, InvokesOnlyCallbackOnFetchingMore) { | |
| 883 auto service = MakeSnippetsService(); | |
| 884 | |
| 885 MockFunction<void(const std::vector<ContentSuggestion>&)> loaded; | |
| 886 EXPECT_CALL(loaded, Call(SizeIs(1))); | |
| 887 | |
| 888 LoadMoreFromJSONString( | |
| 889 service.get(), GetTestJson({GetSnippetWithUrl("http://some")}), | |
| 890 std::set<std::string>(), base::Bind(&SuggestionsLoaded, &loaded)); | |
| 891 | |
| 892 // The observer shouldn't have been triggered. | |
| 893 EXPECT_THAT(observer().SuggestionsForCategory(articles_category()), | |
| 894 IsEmpty()); | |
| 895 } | |
| 896 | |
| 897 TEST_F(NTPSnippetsServiceTest, ReturnFetchRequestEmptyBeforeInit) { | |
| 898 auto service = MakeSnippetsServiceWithoutInitialization(); | |
| 899 MockFunction<void(const std::vector<ContentSuggestion>&)> loaded; | |
| 900 EXPECT_CALL(loaded, Call(SizeIs(0))); | |
| 901 service->Fetch(articles_category(), std::set<std::string>(), | |
| 902 base::Bind(&SuggestionsLoaded, &loaded)); | |
| 903 base::RunLoop().RunUntilIdle(); | |
| 904 } | |
| 905 | |
| 835 TEST_F(NTPSnippetsServiceTest, LoadInvalidJson) { | 906 TEST_F(NTPSnippetsServiceTest, LoadInvalidJson) { |
| 836 auto service = MakeSnippetsService(); | 907 auto service = MakeSnippetsService(); |
| 837 | 908 |
| 838 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); | 909 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); |
| 839 EXPECT_THAT(service->snippets_fetcher()->last_status(), | 910 EXPECT_THAT(service->snippets_fetcher()->last_status(), |
| 840 StartsWith("Received invalid JSON")); | 911 StartsWith("Received invalid JSON")); |
| 841 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); | 912 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), IsEmpty()); |
| 842 } | 913 } |
| 843 | 914 |
| 844 TEST_F(NTPSnippetsServiceTest, LoadInvalidJsonWithExistingSnippets) { | 915 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))); | 1367 base::StringPrintf("http://localhost/snippet-id-%d", i))); |
| 1297 } | 1368 } |
| 1298 LoadFromJSONString(service.get(), GetTestJson(suggestions)); | 1369 LoadFromJSONString(service.get(), GetTestJson(suggestions)); |
| 1299 // TODO(tschumann): We should probably trim out any additional results and | 1370 // TODO(tschumann): We should probably trim out any additional results and |
| 1300 // only serve the MaxSnippetCount items. | 1371 // only serve the MaxSnippetCount items. |
| 1301 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), | 1372 EXPECT_THAT(service->GetSnippetsForTesting(articles_category()), |
| 1302 SizeIs(service->GetMaxSnippetCountForTesting() + 1)); | 1373 SizeIs(service->GetMaxSnippetCountForTesting() + 1)); |
| 1303 } | 1374 } |
| 1304 | 1375 |
| 1305 } // namespace ntp_snippets | 1376 } // namespace ntp_snippets |
| OLD | NEW |