| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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_fetcher.h" | 5 #include "components/ntp_snippets/remote/remote_suggestions_fetcher.h" |
| 6 | 6 |
| 7 #include <deque> | 7 #include <deque> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <set> | |
| 10 #include <utility> | 9 #include <utility> |
| 11 #include <vector> | 10 #include <vector> |
| 12 | 11 |
| 13 #include "base/json/json_reader.h" | 12 #include "base/json/json_reader.h" |
| 14 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 15 #include "base/strings/stringprintf.h" | |
| 16 #include "base/test/histogram_tester.h" | 14 #include "base/test/histogram_tester.h" |
| 17 #include "base/test/test_mock_time_task_runner.h" | 15 #include "base/test/test_mock_time_task_runner.h" |
| 18 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "base/time/default_clock.h" | 17 #include "base/time/default_clock.h" |
| 20 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 21 #include "base/values.h" | 19 #include "base/values.h" |
| 22 #include "components/ntp_snippets/category.h" | 20 #include "components/ntp_snippets/category.h" |
| 23 #include "components/ntp_snippets/features.h" | 21 #include "components/ntp_snippets/features.h" |
| 24 #include "components/ntp_snippets/ntp_snippets_constants.h" | 22 #include "components/ntp_snippets/ntp_snippets_constants.h" |
| 25 #include "components/ntp_snippets/remote/remote_suggestion.h" | 23 #include "components/ntp_snippets/remote/remote_suggestion.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 38 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
| 39 | 37 |
| 40 namespace ntp_snippets { | 38 namespace ntp_snippets { |
| 41 | 39 |
| 42 namespace { | 40 namespace { |
| 43 | 41 |
| 44 using testing::_; | 42 using testing::_; |
| 45 using testing::AllOf; | 43 using testing::AllOf; |
| 46 using testing::ElementsAre; | 44 using testing::ElementsAre; |
| 47 using testing::Eq; | 45 using testing::Eq; |
| 48 using testing::Field; | |
| 49 using testing::IsEmpty; | 46 using testing::IsEmpty; |
| 50 using testing::Not; | 47 using testing::Not; |
| 51 using testing::NotNull; | 48 using testing::NotNull; |
| 52 using testing::Pointee; | |
| 53 using testing::PrintToString; | |
| 54 using testing::Return; | |
| 55 using testing::StartsWith; | 49 using testing::StartsWith; |
| 56 using testing::WithArg; | |
| 57 | 50 |
| 58 const char kAPIKey[] = "fakeAPIkey"; | 51 const char kAPIKey[] = "fakeAPIkey"; |
| 59 const char kTestChromeReaderUrl[] = | |
| 60 "https://chromereader-pa.googleapis.com/v1/fetch?key=fakeAPIkey"; | |
| 61 const char kTestChromeContentSuggestionsSignedOutUrl[] = | 52 const char kTestChromeContentSuggestionsSignedOutUrl[] = |
| 62 "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/" | 53 "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/" |
| 63 "fetch?key=fakeAPIkey"; | 54 "fetch?key=fakeAPIkey"; |
| 64 const char kTestChromeContentSuggestionsSignedInUrl[] = | 55 const char kTestChromeContentSuggestionsSignedInUrl[] = |
| 65 "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/fetch"; | 56 "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/fetch"; |
| 66 | 57 |
| 67 const char kTestEmail[] = "foo@bar.com"; | 58 const char kTestEmail[] = "foo@bar.com"; |
| 68 | 59 |
| 69 // Artificial time delay for JSON parsing. | 60 // Artificial time delay for JSON parsing. |
| 70 const int64_t kTestJsonParsingLatencyMs = 20; | 61 const int64_t kTestJsonParsingLatencyMs = 20; |
| 71 | 62 |
| 72 ACTION_P(MoveArgument1PointeeTo, ptr) { | 63 ACTION_P(MoveArgument1PointeeTo, ptr) { |
| 73 *ptr = std::move(*arg1); | 64 *ptr = std::move(*arg1); |
| 74 } | 65 } |
| 75 | 66 |
| 76 MATCHER(HasValue, "") { | 67 MATCHER(HasValue, "") { |
| 77 return static_cast<bool>(*arg); | 68 return static_cast<bool>(*arg); |
| 78 } | 69 } |
| 79 | 70 |
| 80 // TODO(fhorschig): When there are more helpers for the Status class, consider a | 71 // TODO(fhorschig): When there are more helpers for the Status class, consider a |
| 81 // helpers file. | 72 // helpers file. |
| 82 MATCHER_P(HasCode, code, "") { | 73 MATCHER_P(HasCode, code, "") { |
| 83 return arg.code == code; | 74 return arg.code == code; |
| 84 } | 75 } |
| 85 | 76 |
| 86 MATCHER(IsSuccess, "") { | 77 MATCHER(IsSuccess, "") { |
| 87 return arg.IsSuccess(); | 78 return arg.IsSuccess(); |
| 88 } | 79 } |
| 89 | 80 |
| 81 MATCHER(IsEmptyCategoriesList, "is an empty list of categories") { |
| 82 RemoteSuggestionsFetcher::OptionalFetchedCategories& fetched_categories = |
| 83 *arg; |
| 84 return fetched_categories && fetched_categories->empty(); |
| 85 } |
| 86 |
| 90 MATCHER(IsEmptyArticleList, "is an empty list of articles") { | 87 MATCHER(IsEmptyArticleList, "is an empty list of articles") { |
| 91 RemoteSuggestionsFetcher::OptionalFetchedCategories& fetched_categories = | 88 RemoteSuggestionsFetcher::OptionalFetchedCategories& fetched_categories = |
| 92 *arg; | 89 *arg; |
| 93 return fetched_categories && fetched_categories->size() == 1 && | 90 return fetched_categories && fetched_categories->size() == 1 && |
| 94 fetched_categories->begin()->suggestions.empty(); | 91 fetched_categories->begin()->suggestions.empty(); |
| 95 } | 92 } |
| 96 | 93 |
| 97 MATCHER_P(IsSingleArticle, url, "is a list with the single article %(url)s") { | 94 MATCHER_P(IsSingleArticle, url, "is a list with the single article %(url)s") { |
| 98 RemoteSuggestionsFetcher::OptionalFetchedCategories& fetched_categories = | 95 RemoteSuggestionsFetcher::OptionalFetchedCategories& fetched_categories = |
| 99 *arg; | 96 *arg; |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_; | 384 std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_; |
| 388 std::unique_ptr<RemoteSuggestionsFetcher> fetcher_; | 385 std::unique_ptr<RemoteSuggestionsFetcher> fetcher_; |
| 389 std::unique_ptr<UserClassifier> user_classifier_; | 386 std::unique_ptr<UserClassifier> user_classifier_; |
| 390 MockSnippetsAvailableCallback mock_callback_; | 387 MockSnippetsAvailableCallback mock_callback_; |
| 391 const GURL test_url_; | 388 const GURL test_url_; |
| 392 base::HistogramTester histogram_tester_; | 389 base::HistogramTester histogram_tester_; |
| 393 | 390 |
| 394 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcherTestBase); | 391 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcherTestBase); |
| 395 }; | 392 }; |
| 396 | 393 |
| 397 class RemoteSuggestionsChromeReaderFetcherTest | |
| 398 : public RemoteSuggestionsFetcherTestBase { | |
| 399 public: | |
| 400 RemoteSuggestionsChromeReaderFetcherTest() | |
| 401 : RemoteSuggestionsFetcherTestBase(GURL(kTestChromeReaderUrl)) { | |
| 402 default_variation_params_["content_suggestions_backend"] = | |
| 403 kChromeReaderServer; | |
| 404 SetVariationParam("content_suggestions_backend", kChromeReaderServer); | |
| 405 ResetFetcher(); | |
| 406 } | |
| 407 }; | |
| 408 | |
| 409 class RemoteSuggestionsSignedOutFetcherTest | 394 class RemoteSuggestionsSignedOutFetcherTest |
| 410 : public RemoteSuggestionsFetcherTestBase { | 395 : public RemoteSuggestionsFetcherTestBase { |
| 411 public: | 396 public: |
| 412 RemoteSuggestionsSignedOutFetcherTest() | 397 RemoteSuggestionsSignedOutFetcherTest() |
| 413 : RemoteSuggestionsFetcherTestBase( | 398 : RemoteSuggestionsFetcherTestBase( |
| 414 GURL(kTestChromeContentSuggestionsSignedOutUrl)) {} | 399 GURL(kTestChromeContentSuggestionsSignedOutUrl)) {} |
| 415 }; | 400 }; |
| 416 | 401 |
| 417 // TODO(jkrcal): Add unit-tests for the "authentication in progress" case as it | 402 // TODO(jkrcal): Add unit-tests for the "authentication in progress" case as it |
| 418 // requires more changes (instead FakeSigninManagerBase use FakeSigninManager | 403 // requires more changes (instead FakeSigninManagerBase use FakeSigninManager |
| 419 // which does not exist on ChromeOS). crbug.com/688310 | 404 // which does not exist on ChromeOS). crbug.com/688310 |
| 420 class RemoteSuggestionsSignedInFetcherTest | 405 class RemoteSuggestionsSignedInFetcherTest |
| 421 : public RemoteSuggestionsFetcherTestBase { | 406 : public RemoteSuggestionsFetcherTestBase { |
| 422 public: | 407 public: |
| 423 RemoteSuggestionsSignedInFetcherTest() | 408 RemoteSuggestionsSignedInFetcherTest() |
| 424 : RemoteSuggestionsFetcherTestBase( | 409 : RemoteSuggestionsFetcherTestBase( |
| 425 GURL(kTestChromeContentSuggestionsSignedInUrl)) {} | 410 GURL(kTestChromeContentSuggestionsSignedInUrl)) {} |
| 426 }; | 411 }; |
| 427 | 412 |
| 428 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldNotFetchOnCreation) { | 413 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldNotFetchOnCreation) { |
| 429 // The lack of registered baked in responses would cause any fetch to fail. | 414 // The lack of registered baked in responses would cause any fetch to fail. |
| 430 FastForwardUntilNoTasksRemain(); | 415 FastForwardUntilNoTasksRemain(); |
| 431 EXPECT_THAT(histogram_tester().GetAllSamples( | 416 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 432 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 417 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 433 IsEmpty()); | 418 IsEmpty()); |
| 434 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 419 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 435 IsEmpty()); | 420 IsEmpty()); |
| 436 EXPECT_THAT(fetcher().last_status(), IsEmpty()); | 421 EXPECT_THAT(fetcher().last_status(), IsEmpty()); |
| 437 } | 422 } |
| 438 | 423 |
| 439 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldFetchSuccessfully) { | |
| 440 const std::string kJsonStr = | |
| 441 "{\"recos\": [{" | |
| 442 " \"contentInfo\": {" | |
| 443 " \"url\" : \"http://localhost/foobar\"," | |
| 444 " \"sourceCorpusInfo\" : [{" | |
| 445 " \"ampUrl\" : \"http://localhost/amp\"," | |
| 446 " \"corpusId\" : \"http://localhost/foobar\"," | |
| 447 " \"publisherData\": { \"sourceName\" : \"Foo News\" }" | |
| 448 " }]" | |
| 449 " }" | |
| 450 "}]}"; | |
| 451 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | |
| 452 net::URLRequestStatus::SUCCESS); | |
| 453 EXPECT_CALL(mock_callback(), | |
| 454 Run(IsSuccess(), | |
| 455 AllOf(IsSingleArticle("http://localhost/foobar"), | |
| 456 FirstCategoryHasInfo(IsCategoryInfoForArticles())))); | |
| 457 fetcher().FetchSnippets(test_params(), | |
| 458 ToSnippetsAvailableCallback(&mock_callback())); | |
| 459 FastForwardUntilNoTasksRemain(); | |
| 460 EXPECT_THAT(fetcher().last_status(), Eq("OK")); | |
| 461 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); | |
| 462 EXPECT_THAT(histogram_tester().GetAllSamples( | |
| 463 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | |
| 464 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | |
| 465 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | |
| 466 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | |
| 467 /*count=*/1))); | |
| 468 } | |
| 469 | |
| 470 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldFetchSuccessfully) { | 424 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldFetchSuccessfully) { |
| 471 const std::string kJsonStr = | 425 const std::string kJsonStr = |
| 472 "{\"categories\" : [{" | 426 "{\"categories\" : [{" |
| 473 " \"id\": 1," | 427 " \"id\": 1," |
| 474 " \"localizedTitle\": \"Articles for You\"," | 428 " \"localizedTitle\": \"Articles for You\"," |
| 475 " \"suggestions\" : [{" | 429 " \"suggestions\" : [{" |
| 476 " \"ids\" : [\"http://localhost/foobar\"]," | 430 " \"ids\" : [\"http://localhost/foobar\"]," |
| 477 " \"title\" : \"Foo Barred from Baz\"," | 431 " \"title\" : \"Foo Barred from Baz\"," |
| 478 " \"snippet\" : \"...\"," | 432 " \"snippet\" : \"...\"," |
| 479 " \"fullPageUrl\" : \"http://localhost/foobar\"," | 433 " \"fullPageUrl\" : \"http://localhost/foobar\"," |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 FastForwardUntilNoTasksRemain(); | 766 FastForwardUntilNoTasksRemain(); |
| 813 | 767 |
| 814 EXPECT_THAT(fetcher().last_status(), Eq("No API key available.")); | 768 EXPECT_THAT(fetcher().last_status(), Eq("No API key available.")); |
| 815 EXPECT_THAT(histogram_tester().GetAllSamples( | 769 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 816 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 770 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 817 IsEmpty()); | 771 IsEmpty()); |
| 818 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 772 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 819 IsEmpty()); | 773 IsEmpty()); |
| 820 } | 774 } |
| 821 | 775 |
| 822 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, | 776 TEST_F(RemoteSuggestionsSignedOutFetcherTest, |
| 823 ShouldFetchSuccessfullyEmptyList) { | 777 ShouldFetchSuccessfullyEmptyList) { |
| 824 const std::string kJsonStr = "{\"recos\": []}"; | 778 const std::string kJsonStr = "{\"categories\": []}"; |
| 825 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 779 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 826 net::URLRequestStatus::SUCCESS); | 780 net::URLRequestStatus::SUCCESS); |
| 827 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())); | 781 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyCategoriesList())); |
| 828 fetcher().FetchSnippets(test_params(), | 782 fetcher().FetchSnippets(test_params(), |
| 829 ToSnippetsAvailableCallback(&mock_callback())); | 783 ToSnippetsAvailableCallback(&mock_callback())); |
| 830 FastForwardUntilNoTasksRemain(); | 784 FastForwardUntilNoTasksRemain(); |
| 831 EXPECT_THAT(fetcher().last_status(), Eq("OK")); | 785 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 832 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); | 786 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 833 EXPECT_THAT( | 787 EXPECT_THAT( |
| 834 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 788 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 835 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); | 789 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); |
| 836 EXPECT_THAT(histogram_tester().GetAllSamples( | 790 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 837 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 791 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 838 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 792 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 839 } | 793 } |
| 840 | 794 |
| 841 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, RetryOnInteractiveRequests) { | 795 TEST_F(RemoteSuggestionsSignedOutFetcherTest, RetryOnInteractiveRequests) { |
| 842 DelegateCallingTestURLFetcherFactory fetcher_factory; | 796 DelegateCallingTestURLFetcherFactory fetcher_factory; |
| 843 RequestParams params = test_params(); | 797 RequestParams params = test_params(); |
| 844 params.interactive_request = true; | 798 params.interactive_request = true; |
| 845 | 799 |
| 846 fetcher().FetchSnippets(params, | 800 fetcher().FetchSnippets(params, |
| 847 ToSnippetsAvailableCallback(&mock_callback())); | 801 ToSnippetsAvailableCallback(&mock_callback())); |
| 848 | 802 |
| 849 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); | 803 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); |
| 850 ASSERT_THAT(fetcher, NotNull()); | 804 ASSERT_THAT(fetcher, NotNull()); |
| 851 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(2)); | 805 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(2)); |
| 852 } | 806 } |
| 853 | 807 |
| 854 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, | 808 TEST_F(RemoteSuggestionsSignedOutFetcherTest, |
| 855 RetriesConfigurableOnNonInteractiveRequests) { | 809 RetriesConfigurableOnNonInteractiveRequests) { |
| 856 struct ExpectationForVariationParam { | 810 struct ExpectationForVariationParam { |
| 857 std::string param_value; | 811 std::string param_value; |
| 858 int expected_value; | 812 int expected_value; |
| 859 std::string description; | 813 std::string description; |
| 860 }; | 814 }; |
| 861 const std::vector<ExpectationForVariationParam> retry_config_expectation = { | 815 const std::vector<ExpectationForVariationParam> retry_config_expectation = { |
| 862 {"", 0, "Do not retry by default"}, | 816 {"", 0, "Do not retry by default"}, |
| 863 {"0", 0, "Do not retry on param value 0"}, | 817 {"0", 0, "Do not retry on param value 0"}, |
| 864 {"-1", 0, "Do not retry on negative param values."}, | 818 {"-1", 0, "Do not retry on negative param values."}, |
| 865 {"4", 4, "Retry as set in param value."}}; | 819 {"4", 4, "Retry as set in param value."}}; |
| 866 | 820 |
| 867 RequestParams params = test_params(); | 821 RequestParams params = test_params(); |
| 868 params.interactive_request = false; | 822 params.interactive_request = false; |
| 869 | 823 |
| 870 for (const auto& retry_config : retry_config_expectation) { | 824 for (const auto& retry_config : retry_config_expectation) { |
| 871 DelegateCallingTestURLFetcherFactory fetcher_factory; | 825 DelegateCallingTestURLFetcherFactory fetcher_factory; |
| 872 SetVariationParam("background_5xx_retries_count", retry_config.param_value); | 826 SetVariationParam("background_5xx_retries_count", retry_config.param_value); |
| 873 | 827 |
| 874 fetcher().FetchSnippets(params, | 828 fetcher().FetchSnippets(params, |
| 875 ToSnippetsAvailableCallback(&mock_callback())); | 829 ToSnippetsAvailableCallback(&mock_callback())); |
| 876 | 830 |
| 877 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); | 831 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); |
| 878 ASSERT_THAT(fetcher, NotNull()); | 832 ASSERT_THAT(fetcher, NotNull()); |
| 879 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(retry_config.expected_value)) | 833 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(retry_config.expected_value)) |
| 880 << retry_config.description; | 834 << retry_config.description; |
| 881 } | 835 } |
| 882 } | 836 } |
| 883 | 837 |
| 884 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportUrlStatusError) { | 838 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportUrlStatusError) { |
| 885 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, | 839 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, |
| 886 net::URLRequestStatus::FAILED); | 840 net::URLRequestStatus::FAILED); |
| 887 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 841 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 888 /*snippets=*/Not(HasValue()))) | 842 /*snippets=*/Not(HasValue()))) |
| 889 .Times(1); | 843 .Times(1); |
| 890 fetcher().FetchSnippets(test_params(), | 844 fetcher().FetchSnippets(test_params(), |
| 891 ToSnippetsAvailableCallback(&mock_callback())); | 845 ToSnippetsAvailableCallback(&mock_callback())); |
| 892 FastForwardUntilNoTasksRemain(); | 846 FastForwardUntilNoTasksRemain(); |
| 893 EXPECT_THAT(fetcher().last_status(), Eq("URLRequestStatus error -2")); | 847 EXPECT_THAT(fetcher().last_status(), Eq("URLRequestStatus error -2")); |
| 894 EXPECT_THAT(fetcher().last_json(), IsEmpty()); | 848 EXPECT_THAT(fetcher().last_json(), IsEmpty()); |
| 895 EXPECT_THAT( | 849 EXPECT_THAT( |
| 896 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 850 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 897 ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); | 851 ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); |
| 898 EXPECT_THAT(histogram_tester().GetAllSamples( | 852 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 899 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 853 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 900 ElementsAre(base::Bucket(/*min=*/-2, /*count=*/1))); | 854 ElementsAre(base::Bucket(/*min=*/-2, /*count=*/1))); |
| 901 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 855 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 902 Not(IsEmpty())); | 856 Not(IsEmpty())); |
| 903 } | 857 } |
| 904 | 858 |
| 905 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportHttpError) { | 859 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportHttpError) { |
| 906 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, | 860 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, |
| 907 net::URLRequestStatus::SUCCESS); | 861 net::URLRequestStatus::SUCCESS); |
| 908 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 862 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 909 /*snippets=*/Not(HasValue()))) | 863 /*snippets=*/Not(HasValue()))) |
| 910 .Times(1); | 864 .Times(1); |
| 911 fetcher().FetchSnippets(test_params(), | 865 fetcher().FetchSnippets(test_params(), |
| 912 ToSnippetsAvailableCallback(&mock_callback())); | 866 ToSnippetsAvailableCallback(&mock_callback())); |
| 913 FastForwardUntilNoTasksRemain(); | 867 FastForwardUntilNoTasksRemain(); |
| 914 EXPECT_THAT(fetcher().last_json(), IsEmpty()); | 868 EXPECT_THAT(fetcher().last_json(), IsEmpty()); |
| 915 EXPECT_THAT( | 869 EXPECT_THAT( |
| 916 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 870 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 917 ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); | 871 ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); |
| 918 EXPECT_THAT(histogram_tester().GetAllSamples( | 872 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 919 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 873 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 920 ElementsAre(base::Bucket(/*min=*/404, /*count=*/1))); | 874 ElementsAre(base::Bucket(/*min=*/404, /*count=*/1))); |
| 921 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 875 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 922 Not(IsEmpty())); | 876 Not(IsEmpty())); |
| 923 } | 877 } |
| 924 | 878 |
| 925 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportJsonError) { | 879 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportJsonError) { |
| 926 const std::string kInvalidJsonStr = "{ \"recos\": []"; | 880 const std::string kInvalidJsonStr = "{ \"recos\": []"; |
| 927 SetFakeResponse(/*response_data=*/kInvalidJsonStr, net::HTTP_OK, | 881 SetFakeResponse(/*response_data=*/kInvalidJsonStr, net::HTTP_OK, |
| 928 net::URLRequestStatus::SUCCESS); | 882 net::URLRequestStatus::SUCCESS); |
| 929 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 883 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 930 /*snippets=*/Not(HasValue()))) | 884 /*snippets=*/Not(HasValue()))) |
| 931 .Times(1); | 885 .Times(1); |
| 932 fetcher().FetchSnippets(test_params(), | 886 fetcher().FetchSnippets(test_params(), |
| 933 ToSnippetsAvailableCallback(&mock_callback())); | 887 ToSnippetsAvailableCallback(&mock_callback())); |
| 934 FastForwardUntilNoTasksRemain(); | 888 FastForwardUntilNoTasksRemain(); |
| 935 EXPECT_THAT(fetcher().last_status(), | 889 EXPECT_THAT(fetcher().last_status(), |
| 936 StartsWith("Received invalid JSON (error ")); | 890 StartsWith("Received invalid JSON (error ")); |
| 937 EXPECT_THAT(fetcher().last_json(), Eq(kInvalidJsonStr)); | 891 EXPECT_THAT(fetcher().last_json(), Eq(kInvalidJsonStr)); |
| 938 EXPECT_THAT( | 892 EXPECT_THAT( |
| 939 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 893 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 940 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); | 894 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); |
| 941 EXPECT_THAT(histogram_tester().GetAllSamples( | 895 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 942 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 896 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 943 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 897 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 944 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 898 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 945 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | 899 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 946 /*count=*/1))); | 900 /*count=*/1))); |
| 947 } | 901 } |
| 948 | 902 |
| 949 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, | 903 TEST_F(RemoteSuggestionsSignedOutFetcherTest, |
| 950 ShouldReportJsonErrorForEmptyResponse) { | 904 ShouldReportJsonErrorForEmptyResponse) { |
| 951 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_OK, | 905 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_OK, |
| 952 net::URLRequestStatus::SUCCESS); | 906 net::URLRequestStatus::SUCCESS); |
| 953 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 907 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 954 /*snippets=*/Not(HasValue()))) | 908 /*snippets=*/Not(HasValue()))) |
| 955 .Times(1); | 909 .Times(1); |
| 956 fetcher().FetchSnippets(test_params(), | 910 fetcher().FetchSnippets(test_params(), |
| 957 ToSnippetsAvailableCallback(&mock_callback())); | 911 ToSnippetsAvailableCallback(&mock_callback())); |
| 958 FastForwardUntilNoTasksRemain(); | 912 FastForwardUntilNoTasksRemain(); |
| 959 EXPECT_THAT(fetcher().last_json(), std::string()); | 913 EXPECT_THAT(fetcher().last_json(), std::string()); |
| 960 EXPECT_THAT( | 914 EXPECT_THAT( |
| 961 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 915 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 962 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); | 916 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); |
| 963 EXPECT_THAT(histogram_tester().GetAllSamples( | 917 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 964 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 918 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 965 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 919 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 966 } | 920 } |
| 967 | 921 |
| 968 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportInvalidListError) { | 922 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldReportInvalidListError) { |
| 969 const std::string kJsonStr = | 923 const std::string kJsonStr = |
| 970 "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}"; | 924 "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}"; |
| 971 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 925 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 972 net::URLRequestStatus::SUCCESS); | 926 net::URLRequestStatus::SUCCESS); |
| 973 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 927 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 974 /*snippets=*/Not(HasValue()))) | 928 /*snippets=*/Not(HasValue()))) |
| 975 .Times(1); | 929 .Times(1); |
| 976 fetcher().FetchSnippets(test_params(), | 930 fetcher().FetchSnippets(test_params(), |
| 977 ToSnippetsAvailableCallback(&mock_callback())); | 931 ToSnippetsAvailableCallback(&mock_callback())); |
| 978 FastForwardUntilNoTasksRemain(); | 932 FastForwardUntilNoTasksRemain(); |
| 979 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); | 933 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 980 EXPECT_THAT( | 934 EXPECT_THAT( |
| 981 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 935 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 982 ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); | 936 ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); |
| 983 EXPECT_THAT(histogram_tester().GetAllSamples( | 937 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 984 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 938 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 985 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 939 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 986 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 940 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 987 Not(IsEmpty())); | 941 Not(IsEmpty())); |
| 988 } | 942 } |
| 989 | 943 |
| 990 // This test actually verifies that the test setup itself is sane, to prevent | 944 // This test actually verifies that the test setup itself is sane, to prevent |
| 991 // hard-to-reproduce test failures. | 945 // hard-to-reproduce test failures. |
| 992 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, | 946 TEST_F(RemoteSuggestionsSignedOutFetcherTest, |
| 993 ShouldReportHttpErrorForMissingBakedResponse) { | 947 ShouldReportHttpErrorForMissingBakedResponse) { |
| 994 InitFakeURLFetcherFactory(); | 948 InitFakeURLFetcherFactory(); |
| 995 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 949 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 996 /*snippets=*/Not(HasValue()))) | 950 /*snippets=*/Not(HasValue()))) |
| 997 .Times(1); | 951 .Times(1); |
| 998 fetcher().FetchSnippets(test_params(), | 952 fetcher().FetchSnippets(test_params(), |
| 999 ToSnippetsAvailableCallback(&mock_callback())); | 953 ToSnippetsAvailableCallback(&mock_callback())); |
| 1000 FastForwardUntilNoTasksRemain(); | 954 FastForwardUntilNoTasksRemain(); |
| 1001 } | 955 } |
| 1002 | 956 |
| 1003 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, | 957 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldProcessConcurrentFetches) { |
| 1004 ShouldProcessConcurrentFetches) { | 958 const std::string kJsonStr = "{ \"categories\": [] }"; |
| 1005 const std::string kJsonStr = "{ \"recos\": [] }"; | |
| 1006 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 959 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 1007 net::URLRequestStatus::SUCCESS); | 960 net::URLRequestStatus::SUCCESS); |
| 1008 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())).Times(5); | 961 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyCategoriesList())) |
| 962 .Times(5); |
| 1009 fetcher().FetchSnippets(test_params(), | 963 fetcher().FetchSnippets(test_params(), |
| 1010 ToSnippetsAvailableCallback(&mock_callback())); | 964 ToSnippetsAvailableCallback(&mock_callback())); |
| 1011 // More calls to FetchSnippets() do not interrupt the previous. | 965 // More calls to FetchSnippets() do not interrupt the previous. |
| 1012 // Callback is expected to be called once each time. | 966 // Callback is expected to be called once each time. |
| 1013 fetcher().FetchSnippets(test_params(), | 967 fetcher().FetchSnippets(test_params(), |
| 1014 ToSnippetsAvailableCallback(&mock_callback())); | 968 ToSnippetsAvailableCallback(&mock_callback())); |
| 1015 fetcher().FetchSnippets(test_params(), | 969 fetcher().FetchSnippets(test_params(), |
| 1016 ToSnippetsAvailableCallback(&mock_callback())); | 970 ToSnippetsAvailableCallback(&mock_callback())); |
| 1017 fetcher().FetchSnippets(test_params(), | 971 fetcher().FetchSnippets(test_params(), |
| 1018 ToSnippetsAvailableCallback(&mock_callback())); | 972 ToSnippetsAvailableCallback(&mock_callback())); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1036 fetched_categories) { | 990 fetched_categories) { |
| 1037 if (fetched_categories) { | 991 if (fetched_categories) { |
| 1038 // Matchers above aren't any more precise than this, so this is sufficient | 992 // Matchers above aren't any more precise than this, so this is sufficient |
| 1039 // for test-failure diagnostics. | 993 // for test-failure diagnostics. |
| 1040 return os << "list with " << fetched_categories->size() << " elements"; | 994 return os << "list with " << fetched_categories->size() << " elements"; |
| 1041 } | 995 } |
| 1042 return os << "null"; | 996 return os << "null"; |
| 1043 } | 997 } |
| 1044 | 998 |
| 1045 } // namespace ntp_snippets | 999 } // namespace ntp_snippets |
| OLD | NEW |