| 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> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "base/test/histogram_tester.h" | 16 #include "base/test/histogram_tester.h" |
| 17 #include "base/test/test_mock_time_task_runner.h" | 17 #include "base/test/test_mock_time_task_runner.h" |
| 18 #include "base/threading/thread_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| 20 #include "base/values.h" | 20 #include "base/values.h" |
| 21 #include "components/ntp_snippets/category.h" | 21 #include "components/ntp_snippets/category.h" |
| 22 #include "components/ntp_snippets/features.h" | 22 #include "components/ntp_snippets/features.h" |
| 23 #include "components/ntp_snippets/ntp_snippets_constants.h" | 23 #include "components/ntp_snippets/ntp_snippets_constants.h" |
| 24 #include "components/ntp_snippets/remote/remote_suggestion.h" | 24 #include "components/ntp_snippets/remote/remote_suggestion.h" |
| 25 #include "components/ntp_snippets/remote/request_params.h" | 25 #include "components/ntp_snippets/remote/request_params.h" |
| 26 #include "components/ntp_snippets/remote/test_utils.h" |
| 26 #include "components/ntp_snippets/user_classifier.h" | 27 #include "components/ntp_snippets/user_classifier.h" |
| 27 #include "components/prefs/testing_pref_service.h" | 28 #include "components/prefs/testing_pref_service.h" |
| 28 #include "components/signin/core/browser/account_tracker_service.h" | |
| 29 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" | 29 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" |
| 30 #include "components/signin/core/browser/fake_signin_manager.h" | 30 #include "components/signin/core/browser/fake_signin_manager.h" |
| 31 #include "components/signin/core/browser/test_signin_client.h" | |
| 32 #include "components/variations/entropy_provider.h" | 31 #include "components/variations/entropy_provider.h" |
| 33 #include "components/variations/variations_params_manager.h" | 32 #include "components/variations/variations_params_manager.h" |
| 33 #include "google_apis/gaia/fake_oauth2_token_service_delegate.h" |
| 34 #include "net/url_request/test_url_fetcher_factory.h" | 34 #include "net/url_request/test_url_fetcher_factory.h" |
| 35 #include "net/url_request/url_request_test_util.h" | 35 #include "net/url_request/url_request_test_util.h" |
| 36 #include "testing/gmock/include/gmock/gmock.h" | 36 #include "testing/gmock/include/gmock/gmock.h" |
| 37 #include "testing/gtest/include/gtest/gtest.h" | 37 #include "testing/gtest/include/gtest/gtest.h" |
| 38 | 38 |
| 39 namespace ntp_snippets { | 39 namespace ntp_snippets { |
| 40 | 40 |
| 41 namespace { | 41 namespace { |
| 42 | 42 |
| 43 using testing::_; | 43 using testing::_; |
| 44 using testing::AllOf; | 44 using testing::AllOf; |
| 45 using testing::ElementsAre; | 45 using testing::ElementsAre; |
| 46 using testing::Eq; | 46 using testing::Eq; |
| 47 using testing::Field; | 47 using testing::Field; |
| 48 using testing::IsEmpty; | 48 using testing::IsEmpty; |
| 49 using testing::Not; | 49 using testing::Not; |
| 50 using testing::NotNull; | 50 using testing::NotNull; |
| 51 using testing::Pointee; | 51 using testing::Pointee; |
| 52 using testing::PrintToString; | 52 using testing::PrintToString; |
| 53 using testing::Return; | 53 using testing::Return; |
| 54 using testing::StartsWith; | 54 using testing::StartsWith; |
| 55 using testing::WithArg; | 55 using testing::WithArg; |
| 56 | 56 |
| 57 const char kAPIKey[] = "fakeAPIkey"; | 57 const char kAPIKey[] = "fakeAPIkey"; |
| 58 const char kTestChromeReaderUrl[] = | 58 const char kTestChromeReaderUrl[] = |
| 59 "https://chromereader-pa.googleapis.com/v1/fetch?key=fakeAPIkey"; | 59 "https://chromereader-pa.googleapis.com/v1/fetch?key=fakeAPIkey"; |
| 60 const char kTestChromeContentSuggestionsUrl[] = | 60 const char kTestChromeContentSuggestionsSignedOutUrl[] = |
| 61 "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/" | 61 "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/" |
| 62 "fetch?key=fakeAPIkey"; | 62 "fetch?key=fakeAPIkey"; |
| 63 const char kTestChromeContentSuggestionsSignedInUrl[] = |
| 64 "https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/fetch"; |
| 65 |
| 66 const char kTestEmail[] = "foo@bar.com"; |
| 63 | 67 |
| 64 // Artificial time delay for JSON parsing. | 68 // Artificial time delay for JSON parsing. |
| 65 const int64_t kTestJsonParsingLatencyMs = 20; | 69 const int64_t kTestJsonParsingLatencyMs = 20; |
| 66 | 70 |
| 67 ACTION_P(MoveArgument1PointeeTo, ptr) { | 71 ACTION_P(MoveArgument1PointeeTo, ptr) { |
| 68 *ptr = std::move(*arg1); | 72 *ptr = std::move(*arg1); |
| 69 } | 73 } |
| 70 | 74 |
| 71 MATCHER(HasValue, "") { | 75 MATCHER(HasValue, "") { |
| 72 return static_cast<bool>(*arg); | 76 return static_cast<bool>(*arg); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 success_callback.Run(std::move(value)); | 257 success_callback.Run(std::move(value)); |
| 254 } else { | 258 } else { |
| 255 error_callback.Run(json_reader.GetErrorMessage()); | 259 error_callback.Run(json_reader.GetErrorMessage()); |
| 256 } | 260 } |
| 257 } | 261 } |
| 258 | 262 |
| 259 void ParseJsonDelayed(const std::string& json, | 263 void ParseJsonDelayed(const std::string& json, |
| 260 const SuccessCallback& success_callback, | 264 const SuccessCallback& success_callback, |
| 261 const ErrorCallback& error_callback) { | 265 const ErrorCallback& error_callback) { |
| 262 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 266 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 263 FROM_HERE, base::Bind(&ParseJson, json, std::move(success_callback), | 267 FROM_HERE, |
| 264 std::move(error_callback)), | 268 base::Bind(&ParseJson, json, std::move(success_callback), |
| 269 std::move(error_callback)), |
| 265 base::TimeDelta::FromMilliseconds(kTestJsonParsingLatencyMs)); | 270 base::TimeDelta::FromMilliseconds(kTestJsonParsingLatencyMs)); |
| 266 } | 271 } |
| 267 | 272 |
| 268 } // namespace | 273 } // namespace |
| 269 | 274 |
| 270 // TODO(jkrcal): Add unit-tests with signin client being signed in (covering | |
| 271 // sign-in / refresh tokens / access token code). crbug.com/688310 | |
| 272 class RemoteSuggestionsFetcherTestBase : public testing::Test { | 275 class RemoteSuggestionsFetcherTestBase : public testing::Test { |
| 273 public: | 276 public: |
| 274 explicit RemoteSuggestionsFetcherTestBase(const GURL& gurl) | 277 explicit RemoteSuggestionsFetcherTestBase(const GURL& gurl) |
| 275 : default_variation_params_( | 278 : default_variation_params_( |
| 276 {{"send_top_languages", "true"}, {"send_user_class", "true"}}), | 279 {{"send_top_languages", "true"}, {"send_user_class", "true"}}), |
| 277 params_manager_(ntp_snippets::kStudyName, | 280 params_manager_(ntp_snippets::kStudyName, |
| 278 default_variation_params_, | 281 default_variation_params_, |
| 279 {ntp_snippets::kArticleSuggestionsFeature.name}), | 282 {ntp_snippets::kArticleSuggestionsFeature.name}), |
| 280 mock_task_runner_(new base::TestMockTimeTaskRunner()), | 283 mock_task_runner_(new base::TestMockTimeTaskRunner()), |
| 281 mock_task_runner_handle_(mock_task_runner_), | 284 mock_task_runner_handle_(mock_task_runner_), |
| 282 signin_client_(base::MakeUnique<TestSigninClient>(nullptr)), | |
| 283 account_tracker_(base::MakeUnique<AccountTrackerService>()), | |
| 284 fake_signin_manager_( | |
| 285 base::MakeUnique<FakeSigninManagerBase>(signin_client_.get(), | |
| 286 account_tracker_.get())), | |
| 287 fake_token_service_(base::MakeUnique<FakeProfileOAuth2TokenService>()), | |
| 288 pref_service_(base::MakeUnique<TestingPrefServiceSimple>()), | |
| 289 test_url_(gurl) { | 285 test_url_(gurl) { |
| 290 RequestThrottler::RegisterProfilePrefs(pref_service_->registry()); | 286 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); |
| 291 UserClassifier::RegisterProfilePrefs(pref_service_->registry()); | 287 UserClassifier::RegisterProfilePrefs(utils_.pref_service()->registry()); |
| 292 user_classifier_ = base::MakeUnique<UserClassifier>(pref_service_.get()); | 288 user_classifier_ = base::MakeUnique<UserClassifier>(utils_.pref_service()); |
| 293 // Increase initial time such that ticks are non-zero. | 289 // Increase initial time such that ticks are non-zero. |
| 294 mock_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1234)); | 290 mock_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1234)); |
| 295 ResetSnippetsFetcher(); | 291 ResetFetcher(); |
| 296 } | 292 } |
| 297 | 293 |
| 298 void ResetSnippetsFetcher() { | 294 void ResetFetcher() { |
| 299 snippets_fetcher_ = base::MakeUnique<RemoteSuggestionsFetcher>( | 295 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = |
| 300 fake_signin_manager_.get(), fake_token_service_.get(), | 296 new net::TestURLRequestContextGetter(mock_task_runner_.get()); |
| 301 scoped_refptr<net::TestURLRequestContextGetter>( | |
| 302 new net::TestURLRequestContextGetter(mock_task_runner_.get())), | |
| 303 pref_service_.get(), nullptr, base::Bind(&ParseJsonDelayed), kAPIKey, | |
| 304 user_classifier_.get()); | |
| 305 | 297 |
| 306 snippets_fetcher_->SetTickClockForTesting( | 298 fake_token_service_delegate_ = |
| 307 mock_task_runner_->GetMockTickClock()); | 299 new FakeOAuth2TokenServiceDelegate(request_context_getter.get()); |
| 300 // Not a memleak because OAuth2TokenService takes ownership of the raw |
| 301 // pointer (crbug.com/688387). |
| 302 fake_token_service_ = base::MakeUnique<FakeProfileOAuth2TokenService>( |
| 303 fake_token_service_delegate_); |
| 304 |
| 305 fetcher_ = base::MakeUnique<RemoteSuggestionsFetcher>( |
| 306 utils_.fake_signin_manager(), fake_token_service_.get(), |
| 307 std::move(request_context_getter), utils_.pref_service(), nullptr, |
| 308 base::Bind(&ParseJsonDelayed), kAPIKey, user_classifier_.get()); |
| 309 |
| 310 fetcher_->SetTickClockForTesting(mock_task_runner_->GetMockTickClock()); |
| 311 } |
| 312 |
| 313 void SignIn() { utils_.fake_signin_manager()->SignIn(kTestEmail); } |
| 314 |
| 315 void IssueRefreshToken() { |
| 316 fake_token_service_delegate_->UpdateCredentials(kTestEmail, "token"); |
| 317 } |
| 318 |
| 319 void IssueOAuth2Token() { |
| 320 fake_token_service_->IssueAllTokensForAccount(kTestEmail, "access_token", |
| 321 base::Time::Max()); |
| 322 } |
| 323 |
| 324 void CancelOAuth2TokenRequests() { |
| 325 fake_token_service_->IssueErrorForAllPendingRequestsForAccount( |
| 326 kTestEmail, GoogleServiceAuthError( |
| 327 GoogleServiceAuthError::State::REQUEST_CANCELED)); |
| 308 } | 328 } |
| 309 | 329 |
| 310 RemoteSuggestionsFetcher::SnippetsAvailableCallback | 330 RemoteSuggestionsFetcher::SnippetsAvailableCallback |
| 311 ToSnippetsAvailableCallback(MockSnippetsAvailableCallback* callback) { | 331 ToSnippetsAvailableCallback(MockSnippetsAvailableCallback* callback) { |
| 312 return base::BindOnce(&MockSnippetsAvailableCallback::WrappedRun, | 332 return base::BindOnce(&MockSnippetsAvailableCallback::WrappedRun, |
| 313 base::Unretained(callback)); | 333 base::Unretained(callback)); |
| 314 } | 334 } |
| 315 | 335 |
| 316 RemoteSuggestionsFetcher& snippets_fetcher() { return *snippets_fetcher_; } | 336 RemoteSuggestionsFetcher& fetcher() { return *fetcher_; } |
| 317 MockSnippetsAvailableCallback& mock_callback() { return mock_callback_; } | 337 MockSnippetsAvailableCallback& mock_callback() { return mock_callback_; } |
| 318 void FastForwardUntilNoTasksRemain() { | 338 void FastForwardUntilNoTasksRemain() { |
| 319 mock_task_runner_->FastForwardUntilNoTasksRemain(); | 339 mock_task_runner_->FastForwardUntilNoTasksRemain(); |
| 320 } | 340 } |
| 321 base::HistogramTester& histogram_tester() { return histogram_tester_; } | 341 base::HistogramTester& histogram_tester() { return histogram_tester_; } |
| 322 | 342 |
| 323 RequestParams test_params() { | 343 RequestParams test_params() { |
| 324 RequestParams result; | 344 RequestParams result; |
| 325 result.count_to_fetch = 1; | 345 result.count_to_fetch = 1; |
| 326 result.interactive_request = true; | 346 result.interactive_request = true; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 348 } | 368 } |
| 349 | 369 |
| 350 void SetFakeResponse(const std::string& response_data, | 370 void SetFakeResponse(const std::string& response_data, |
| 351 net::HttpStatusCode response_code, | 371 net::HttpStatusCode response_code, |
| 352 net::URLRequestStatus::Status status) { | 372 net::URLRequestStatus::Status status) { |
| 353 InitFakeURLFetcherFactory(); | 373 InitFakeURLFetcherFactory(); |
| 354 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data, | 374 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data, |
| 355 response_code, status); | 375 response_code, status); |
| 356 } | 376 } |
| 357 | 377 |
| 358 TestingPrefServiceSimple* pref_service() const { return pref_service_.get(); } | |
| 359 | |
| 360 protected: | 378 protected: |
| 361 std::map<std::string, std::string> default_variation_params_; | 379 std::map<std::string, std::string> default_variation_params_; |
| 362 | 380 |
| 363 private: | 381 private: |
| 382 test::RemoteSuggestionsTestUtils utils_; |
| 364 variations::testing::VariationParamsManager params_manager_; | 383 variations::testing::VariationParamsManager params_manager_; |
| 365 scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_; | 384 scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_; |
| 366 base::ThreadTaskRunnerHandle mock_task_runner_handle_; | 385 base::ThreadTaskRunnerHandle mock_task_runner_handle_; |
| 367 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; | 386 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; |
| 368 // Initialized lazily in SetFakeResponse(). | 387 // Initialized lazily in SetFakeResponse(). |
| 369 std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_; | 388 std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_; |
| 370 std::unique_ptr<TestSigninClient> signin_client_; | 389 FakeOAuth2TokenServiceDelegate* fake_token_service_delegate_; |
| 371 std::unique_ptr<AccountTrackerService> account_tracker_; | 390 std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_; |
| 372 std::unique_ptr<SigninManagerBase> fake_signin_manager_; | 391 std::unique_ptr<RemoteSuggestionsFetcher> fetcher_; |
| 373 std::unique_ptr<OAuth2TokenService> fake_token_service_; | |
| 374 std::unique_ptr<RemoteSuggestionsFetcher> snippets_fetcher_; | |
| 375 std::unique_ptr<TestingPrefServiceSimple> pref_service_; | |
| 376 std::unique_ptr<UserClassifier> user_classifier_; | 392 std::unique_ptr<UserClassifier> user_classifier_; |
| 377 MockSnippetsAvailableCallback mock_callback_; | 393 MockSnippetsAvailableCallback mock_callback_; |
| 378 const GURL test_url_; | 394 const GURL test_url_; |
| 379 base::HistogramTester histogram_tester_; | 395 base::HistogramTester histogram_tester_; |
| 380 | 396 |
| 381 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcherTestBase); | 397 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsFetcherTestBase); |
| 382 }; | 398 }; |
| 383 | 399 |
| 384 class ChromeReaderSnippetsFetcherTest | 400 class RemoteSuggestionsChromeReaderFetcherTest |
| 385 : public RemoteSuggestionsFetcherTestBase { | 401 : public RemoteSuggestionsFetcherTestBase { |
| 386 public: | 402 public: |
| 387 ChromeReaderSnippetsFetcherTest() | 403 RemoteSuggestionsChromeReaderFetcherTest() |
| 388 : RemoteSuggestionsFetcherTestBase(GURL(kTestChromeReaderUrl)) { | 404 : RemoteSuggestionsFetcherTestBase(GURL(kTestChromeReaderUrl)) { |
| 389 default_variation_params_["content_suggestions_backend"] = | 405 default_variation_params_["content_suggestions_backend"] = |
| 390 kChromeReaderServer; | 406 kChromeReaderServer; |
| 391 SetVariationParam("content_suggestions_backend", kChromeReaderServer); | 407 SetVariationParam("content_suggestions_backend", kChromeReaderServer); |
| 392 ResetSnippetsFetcher(); | 408 ResetFetcher(); |
| 393 } | 409 } |
| 394 }; | 410 }; |
| 395 | 411 |
| 396 class NTPSnippetsContentSuggestionsFetcherTest | 412 class RemoteSuggestionsSignedOutFetcherTest |
| 397 : public RemoteSuggestionsFetcherTestBase { | 413 : public RemoteSuggestionsFetcherTestBase { |
| 398 public: | 414 public: |
| 399 NTPSnippetsContentSuggestionsFetcherTest() | 415 RemoteSuggestionsSignedOutFetcherTest() |
| 400 : RemoteSuggestionsFetcherTestBase( | 416 : RemoteSuggestionsFetcherTestBase( |
| 401 GURL(kTestChromeContentSuggestionsUrl)) {} | 417 GURL(kTestChromeContentSuggestionsSignedOutUrl)) {} |
| 402 }; | 418 }; |
| 403 | 419 |
| 404 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldNotFetchOnCreation) { | 420 // TODO(jkrcal): Add unit-tests for the "authentication in progress" case as it |
| 421 // requires more changes (instead FakeSigninManagerBase use FakeSigninManager |
| 422 // which does not exist on ChromeOS). crbug.com/688310 |
| 423 class RemoteSuggestionsSignedInFetcherTest |
| 424 : public RemoteSuggestionsFetcherTestBase { |
| 425 public: |
| 426 RemoteSuggestionsSignedInFetcherTest() |
| 427 : RemoteSuggestionsFetcherTestBase( |
| 428 GURL(kTestChromeContentSuggestionsSignedInUrl)) {} |
| 429 }; |
| 430 |
| 431 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldNotFetchOnCreation) { |
| 405 // The lack of registered baked in responses would cause any fetch to fail. | 432 // The lack of registered baked in responses would cause any fetch to fail. |
| 406 FastForwardUntilNoTasksRemain(); | 433 FastForwardUntilNoTasksRemain(); |
| 407 EXPECT_THAT(histogram_tester().GetAllSamples( | 434 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 408 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 435 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 409 IsEmpty()); | 436 IsEmpty()); |
| 410 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 437 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 411 IsEmpty()); | 438 IsEmpty()); |
| 412 EXPECT_THAT(snippets_fetcher().last_status(), IsEmpty()); | 439 EXPECT_THAT(fetcher().last_status(), IsEmpty()); |
| 413 } | 440 } |
| 414 | 441 |
| 415 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldFetchSuccessfully) { | 442 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldFetchSuccessfully) { |
| 416 const std::string kJsonStr = | 443 const std::string kJsonStr = |
| 417 "{\"recos\": [{" | 444 "{\"recos\": [{" |
| 418 " \"contentInfo\": {" | 445 " \"contentInfo\": {" |
| 419 " \"url\" : \"http://localhost/foobar\"," | 446 " \"url\" : \"http://localhost/foobar\"," |
| 420 " \"sourceCorpusInfo\" : [{" | 447 " \"sourceCorpusInfo\" : [{" |
| 421 " \"ampUrl\" : \"http://localhost/amp\"," | 448 " \"ampUrl\" : \"http://localhost/amp\"," |
| 422 " \"corpusId\" : \"http://localhost/foobar\"," | 449 " \"corpusId\" : \"http://localhost/foobar\"," |
| 423 " \"publisherData\": { \"sourceName\" : \"Foo News\" }" | 450 " \"publisherData\": { \"sourceName\" : \"Foo News\" }" |
| 424 " }]" | 451 " }]" |
| 425 " }" | 452 " }" |
| 426 "}]}"; | 453 "}]}"; |
| 427 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 454 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 428 net::URLRequestStatus::SUCCESS); | 455 net::URLRequestStatus::SUCCESS); |
| 429 EXPECT_CALL(mock_callback(), | 456 EXPECT_CALL(mock_callback(), |
| 430 Run(IsSuccess(), | 457 Run(IsSuccess(), |
| 431 AllOf(IsSingleArticle("http://localhost/foobar"), | 458 AllOf(IsSingleArticle("http://localhost/foobar"), |
| 432 FirstCategoryHasInfo(IsCategoryInfoForArticles())))); | 459 FirstCategoryHasInfo(IsCategoryInfoForArticles())))); |
| 433 snippets_fetcher().FetchSnippets( | 460 fetcher().FetchSnippets(test_params(), |
| 434 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 461 ToSnippetsAvailableCallback(&mock_callback())); |
| 435 FastForwardUntilNoTasksRemain(); | 462 FastForwardUntilNoTasksRemain(); |
| 436 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); | 463 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 437 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 464 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 438 EXPECT_THAT(histogram_tester().GetAllSamples( | 465 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 439 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 466 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 440 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 467 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 468 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 469 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 470 /*count=*/1))); |
| 471 } |
| 472 |
| 473 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ShouldFetchSuccessfully) { |
| 474 const std::string kJsonStr = |
| 475 "{\"categories\" : [{" |
| 476 " \"id\": 1," |
| 477 " \"localizedTitle\": \"Articles for You\"," |
| 478 " \"suggestions\" : [{" |
| 479 " \"ids\" : [\"http://localhost/foobar\"]," |
| 480 " \"title\" : \"Foo Barred from Baz\"," |
| 481 " \"snippet\" : \"...\"," |
| 482 " \"fullPageUrl\" : \"http://localhost/foobar\"," |
| 483 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," |
| 484 " \"expirationTime\" : \"2016-07-01T11:01:37.000Z\"," |
| 485 " \"attribution\" : \"Foo News\"," |
| 486 " \"imageUrl\" : \"http://localhost/foobar.jpg\"," |
| 487 " \"ampUrl\" : \"http://localhost/amp\"," |
| 488 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " |
| 489 " }]" |
| 490 "}]}"; |
| 491 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 492 net::URLRequestStatus::SUCCESS); |
| 493 EXPECT_CALL(mock_callback(), |
| 494 Run(IsSuccess(), |
| 495 AllOf(IsSingleArticle("http://localhost/foobar"), |
| 496 FirstCategoryHasInfo(IsCategoryInfoForArticles())))); |
| 497 fetcher().FetchSnippets(test_params(), |
| 498 ToSnippetsAvailableCallback(&mock_callback())); |
| 499 FastForwardUntilNoTasksRemain(); |
| 500 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 501 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 502 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 503 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 504 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 505 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 506 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 507 /*count=*/1))); |
| 508 } |
| 509 |
| 510 TEST_F(RemoteSuggestionsSignedInFetcherTest, ShouldFetchSuccessfully) { |
| 511 SignIn(); |
| 512 IssueRefreshToken(); |
| 513 |
| 514 const std::string kJsonStr = |
| 515 "{\"categories\" : [{" |
| 516 " \"id\": 1," |
| 517 " \"localizedTitle\": \"Articles for You\"," |
| 518 " \"suggestions\" : [{" |
| 519 " \"ids\" : [\"http://localhost/foobar\"]," |
| 520 " \"title\" : \"Foo Barred from Baz\"," |
| 521 " \"snippet\" : \"...\"," |
| 522 " \"fullPageUrl\" : \"http://localhost/foobar\"," |
| 523 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," |
| 524 " \"expirationTime\" : \"2016-07-01T11:01:37.000Z\"," |
| 525 " \"attribution\" : \"Foo News\"," |
| 526 " \"imageUrl\" : \"http://localhost/foobar.jpg\"," |
| 527 " \"ampUrl\" : \"http://localhost/amp\"," |
| 528 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " |
| 529 " }]" |
| 530 "}]}"; |
| 531 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 532 net::URLRequestStatus::SUCCESS); |
| 533 EXPECT_CALL(mock_callback(), |
| 534 Run(IsSuccess(), |
| 535 AllOf(IsSingleArticle("http://localhost/foobar"), |
| 536 FirstCategoryHasInfo(IsCategoryInfoForArticles())))); |
| 537 |
| 538 fetcher().FetchSnippets(test_params(), |
| 539 ToSnippetsAvailableCallback(&mock_callback())); |
| 540 |
| 541 IssueOAuth2Token(); |
| 542 // Wait for the fake response. |
| 543 FastForwardUntilNoTasksRemain(); |
| 544 |
| 545 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 546 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 547 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 548 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 549 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 441 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 550 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 442 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | 551 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 443 /*count=*/1))); | 552 /*count=*/1))); |
| 444 } | 553 } |
| 445 | 554 |
| 446 TEST_F(NTPSnippetsContentSuggestionsFetcherTest, ShouldFetchSuccessfully) { | 555 TEST_F(RemoteSuggestionsSignedInFetcherTest, |
| 556 ShouldRetryWhenOAuthCancelled) { |
| 557 SignIn(); |
| 558 IssueRefreshToken(); |
| 559 |
| 447 const std::string kJsonStr = | 560 const std::string kJsonStr = |
| 448 "{\"categories\" : [{" | 561 "{\"categories\" : [{" |
| 449 " \"id\": 1," | 562 " \"id\": 1," |
| 450 " \"localizedTitle\": \"Articles for You\"," | 563 " \"localizedTitle\": \"Articles for You\"," |
| 451 " \"suggestions\" : [{" | 564 " \"suggestions\" : [{" |
| 452 " \"ids\" : [\"http://localhost/foobar\"]," | 565 " \"ids\" : [\"http://localhost/foobar\"]," |
| 453 " \"title\" : \"Foo Barred from Baz\"," | 566 " \"title\" : \"Foo Barred from Baz\"," |
| 454 " \"snippet\" : \"...\"," | 567 " \"snippet\" : \"...\"," |
| 455 " \"fullPageUrl\" : \"http://localhost/foobar\"," | 568 " \"fullPageUrl\" : \"http://localhost/foobar\"," |
| 456 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," | 569 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," |
| 457 " \"expirationTime\" : \"2016-07-01T11:01:37.000Z\"," | 570 " \"expirationTime\" : \"2016-07-01T11:01:37.000Z\"," |
| 458 " \"attribution\" : \"Foo News\"," | 571 " \"attribution\" : \"Foo News\"," |
| 459 " \"imageUrl\" : \"http://localhost/foobar.jpg\"," | 572 " \"imageUrl\" : \"http://localhost/foobar.jpg\"," |
| 460 " \"ampUrl\" : \"http://localhost/amp\"," | 573 " \"ampUrl\" : \"http://localhost/amp\"," |
| 461 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " | 574 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " |
| 462 " }]" | 575 " }]" |
| 463 "}]}"; | 576 "}]}"; |
| 464 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 577 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 465 net::URLRequestStatus::SUCCESS); | 578 net::URLRequestStatus::SUCCESS); |
| 466 EXPECT_CALL(mock_callback(), | 579 EXPECT_CALL(mock_callback(), |
| 467 Run(IsSuccess(), | 580 Run(IsSuccess(), |
| 468 AllOf(IsSingleArticle("http://localhost/foobar"), | 581 AllOf(IsSingleArticle("http://localhost/foobar"), |
| 469 FirstCategoryHasInfo(IsCategoryInfoForArticles())))); | 582 FirstCategoryHasInfo(IsCategoryInfoForArticles())))); |
| 470 snippets_fetcher().FetchSnippets( | 583 |
| 471 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 584 fetcher().FetchSnippets(test_params(), |
| 585 ToSnippetsAvailableCallback(&mock_callback())); |
| 586 |
| 587 CancelOAuth2TokenRequests(); |
| 588 IssueOAuth2Token(); |
| 589 // Wait for the fake response. |
| 472 FastForwardUntilNoTasksRemain(); | 590 FastForwardUntilNoTasksRemain(); |
| 473 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); | 591 |
| 474 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 592 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 593 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 475 EXPECT_THAT(histogram_tester().GetAllSamples( | 594 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 476 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 595 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 477 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 596 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 478 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 597 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 479 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | 598 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 480 /*count=*/1))); | 599 /*count=*/1))); |
| 481 } | 600 } |
| 482 | 601 |
| 483 TEST_F(NTPSnippetsContentSuggestionsFetcherTest, EmptyCategoryIsOK) { | 602 TEST_F(RemoteSuggestionsSignedOutFetcherTest, EmptyCategoryIsOK) { |
| 484 const std::string kJsonStr = | 603 const std::string kJsonStr = |
| 485 "{\"categories\" : [{" | 604 "{\"categories\" : [{" |
| 486 " \"id\": 1," | 605 " \"id\": 1," |
| 487 " \"localizedTitle\": \"Articles for You\"" | 606 " \"localizedTitle\": \"Articles for You\"" |
| 488 "}]}"; | 607 "}]}"; |
| 489 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 608 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 490 net::URLRequestStatus::SUCCESS); | 609 net::URLRequestStatus::SUCCESS); |
| 491 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())); | 610 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())); |
| 492 snippets_fetcher().FetchSnippets( | 611 fetcher().FetchSnippets(test_params(), |
| 493 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 612 ToSnippetsAvailableCallback(&mock_callback())); |
| 494 FastForwardUntilNoTasksRemain(); | 613 FastForwardUntilNoTasksRemain(); |
| 495 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); | 614 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 496 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 615 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 497 EXPECT_THAT(histogram_tester().GetAllSamples( | 616 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 498 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 617 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 499 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 618 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 500 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 619 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 501 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | 620 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 502 /*count=*/1))); | 621 /*count=*/1))); |
| 503 } | 622 } |
| 504 | 623 |
| 505 TEST_F(NTPSnippetsContentSuggestionsFetcherTest, ServerCategories) { | 624 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ServerCategories) { |
| 506 const std::string kJsonStr = | 625 const std::string kJsonStr = |
| 507 "{\"categories\" : [{" | 626 "{\"categories\" : [{" |
| 508 " \"id\": 1," | 627 " \"id\": 1," |
| 509 " \"localizedTitle\": \"Articles for You\"," | 628 " \"localizedTitle\": \"Articles for You\"," |
| 510 " \"suggestions\" : [{" | 629 " \"suggestions\" : [{" |
| 511 " \"ids\" : [\"http://localhost/foobar\"]," | 630 " \"ids\" : [\"http://localhost/foobar\"]," |
| 512 " \"title\" : \"Foo Barred from Baz\"," | 631 " \"title\" : \"Foo Barred from Baz\"," |
| 513 " \"snippet\" : \"...\"," | 632 " \"snippet\" : \"...\"," |
| 514 " \"fullPageUrl\" : \"http://localhost/foobar\"," | 633 " \"fullPageUrl\" : \"http://localhost/foobar\"," |
| 515 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," | 634 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," |
| (...skipping 18 matching lines...) Expand all Loading... |
| 534 " \"imageUrl\" : \"http://localhost/foo2.jpg\"," | 653 " \"imageUrl\" : \"http://localhost/foo2.jpg\"," |
| 535 " \"ampUrl\" : \"http://localhost/amp\"," | 654 " \"ampUrl\" : \"http://localhost/amp\"," |
| 536 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " | 655 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " |
| 537 " }]" | 656 " }]" |
| 538 "}]}"; | 657 "}]}"; |
| 539 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 658 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 540 net::URLRequestStatus::SUCCESS); | 659 net::URLRequestStatus::SUCCESS); |
| 541 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories; | 660 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories; |
| 542 EXPECT_CALL(mock_callback(), Run(IsSuccess(), _)) | 661 EXPECT_CALL(mock_callback(), Run(IsSuccess(), _)) |
| 543 .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); | 662 .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); |
| 544 snippets_fetcher().FetchSnippets( | 663 fetcher().FetchSnippets(test_params(), |
| 545 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 664 ToSnippetsAvailableCallback(&mock_callback())); |
| 546 FastForwardUntilNoTasksRemain(); | 665 FastForwardUntilNoTasksRemain(); |
| 547 | 666 |
| 548 ASSERT_TRUE(fetched_categories); | 667 ASSERT_TRUE(fetched_categories); |
| 549 ASSERT_THAT(fetched_categories->size(), Eq(2u)); | 668 ASSERT_THAT(fetched_categories->size(), Eq(2u)); |
| 550 for (const auto& category : *fetched_categories) { | 669 for (const auto& category : *fetched_categories) { |
| 551 const auto& articles = category.suggestions; | 670 const auto& articles = category.suggestions; |
| 552 if (category.category.IsKnownCategory(KnownCategories::ARTICLES)) { | 671 if (category.category.IsKnownCategory(KnownCategories::ARTICLES)) { |
| 553 ASSERT_THAT(articles.size(), Eq(1u)); | 672 ASSERT_THAT(articles.size(), Eq(1u)); |
| 554 EXPECT_THAT(articles[0]->url().spec(), Eq("http://localhost/foobar")); | 673 EXPECT_THAT(articles[0]->url().spec(), Eq("http://localhost/foobar")); |
| 555 EXPECT_THAT(category.info, IsCategoryInfoForArticles()); | 674 EXPECT_THAT(category.info, IsCategoryInfoForArticles()); |
| 556 } else if (category.category == Category::FromRemoteCategory(2)) { | 675 } else if (category.category == Category::FromRemoteCategory(2)) { |
| 557 ASSERT_THAT(articles.size(), Eq(1u)); | 676 ASSERT_THAT(articles.size(), Eq(1u)); |
| 558 EXPECT_THAT(articles[0]->url().spec(), Eq("http://localhost/foo2")); | 677 EXPECT_THAT(articles[0]->url().spec(), Eq("http://localhost/foo2")); |
| 559 EXPECT_THAT(category.info.has_fetch_action(), Eq(true)); | 678 EXPECT_THAT(category.info.has_fetch_action(), Eq(true)); |
| 560 EXPECT_THAT(category.info.has_view_all_action(), Eq(false)); | 679 EXPECT_THAT(category.info.has_view_all_action(), Eq(false)); |
| 561 EXPECT_THAT(category.info.show_if_empty(), Eq(false)); | 680 EXPECT_THAT(category.info.show_if_empty(), Eq(false)); |
| 562 } else { | 681 } else { |
| 563 FAIL() << "unknown category ID " << category.category.id(); | 682 FAIL() << "unknown category ID " << category.category.id(); |
| 564 } | 683 } |
| 565 } | 684 } |
| 566 | 685 |
| 567 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); | 686 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 568 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 687 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 569 EXPECT_THAT(histogram_tester().GetAllSamples( | 688 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 570 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 689 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 571 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 690 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 572 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 691 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 573 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | 692 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 574 /*count=*/1))); | 693 /*count=*/1))); |
| 575 } | 694 } |
| 576 | 695 |
| 577 TEST_F(NTPSnippetsContentSuggestionsFetcherTest, | 696 TEST_F(RemoteSuggestionsSignedOutFetcherTest, |
| 578 SupportMissingAllowFetchingMoreResultsOption) { | 697 SupportMissingAllowFetchingMoreResultsOption) { |
| 579 // This tests makes sure we handle the missing option although it's required | 698 // This tests makes sure we handle the missing option although it's required |
| 580 // by the interface. It's just that the Service doesn't follow that | 699 // by the interface. It's just that the Service doesn't follow that |
| 581 // requirement (yet). TODO(tschumann): remove this test once not needed | 700 // requirement (yet). TODO(tschumann): remove this test once not needed |
| 582 // anymore. | 701 // anymore. |
| 583 const std::string kJsonStr = | 702 const std::string kJsonStr = |
| 584 "{\"categories\" : [{" | 703 "{\"categories\" : [{" |
| 585 " \"id\": 2," | 704 " \"id\": 2," |
| 586 " \"localizedTitle\": \"Articles for Me\"," | 705 " \"localizedTitle\": \"Articles for Me\"," |
| 587 " \"suggestions\" : [{" | 706 " \"suggestions\" : [{" |
| 588 " \"ids\" : [\"http://localhost/foo2\"]," | 707 " \"ids\" : [\"http://localhost/foo2\"]," |
| 589 " \"title\" : \"Foo Barred from Baz\"," | 708 " \"title\" : \"Foo Barred from Baz\"," |
| 590 " \"snippet\" : \"...\"," | 709 " \"snippet\" : \"...\"," |
| 591 " \"fullPageUrl\" : \"http://localhost/foo2\"," | 710 " \"fullPageUrl\" : \"http://localhost/foo2\"," |
| 592 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," | 711 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," |
| 593 " \"expirationTime\" : \"2016-07-01T11:01:37.000Z\"," | 712 " \"expirationTime\" : \"2016-07-01T11:01:37.000Z\"," |
| 594 " \"attribution\" : \"Foo News\"," | 713 " \"attribution\" : \"Foo News\"," |
| 595 " \"imageUrl\" : \"http://localhost/foo2.jpg\"," | 714 " \"imageUrl\" : \"http://localhost/foo2.jpg\"," |
| 596 " \"ampUrl\" : \"http://localhost/amp\"," | 715 " \"ampUrl\" : \"http://localhost/amp\"," |
| 597 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " | 716 " \"faviconUrl\" : \"http://localhost/favicon.ico\" " |
| 598 " }]" | 717 " }]" |
| 599 "}]}"; | 718 "}]}"; |
| 600 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 719 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 601 net::URLRequestStatus::SUCCESS); | 720 net::URLRequestStatus::SUCCESS); |
| 602 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories; | 721 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories; |
| 603 EXPECT_CALL(mock_callback(), Run(IsSuccess(), _)) | 722 EXPECT_CALL(mock_callback(), Run(IsSuccess(), _)) |
| 604 .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); | 723 .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); |
| 605 snippets_fetcher().FetchSnippets( | 724 fetcher().FetchSnippets(test_params(), |
| 606 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 725 ToSnippetsAvailableCallback(&mock_callback())); |
| 607 FastForwardUntilNoTasksRemain(); | 726 FastForwardUntilNoTasksRemain(); |
| 608 | 727 |
| 609 ASSERT_TRUE(fetched_categories); | 728 ASSERT_TRUE(fetched_categories); |
| 610 ASSERT_THAT(fetched_categories->size(), Eq(1u)); | 729 ASSERT_THAT(fetched_categories->size(), Eq(1u)); |
| 611 EXPECT_THAT(fetched_categories->front().info.has_fetch_action(), Eq(false)); | 730 EXPECT_THAT(fetched_categories->front().info.has_fetch_action(), Eq(false)); |
| 612 EXPECT_THAT(fetched_categories->front().info.title(), | 731 EXPECT_THAT(fetched_categories->front().info.title(), |
| 613 Eq(base::UTF8ToUTF16("Articles for Me"))); | 732 Eq(base::UTF8ToUTF16("Articles for Me"))); |
| 614 } | 733 } |
| 615 | 734 |
| 616 TEST_F(NTPSnippetsContentSuggestionsFetcherTest, ExclusiveCategoryOnly) { | 735 TEST_F(RemoteSuggestionsSignedOutFetcherTest, ExclusiveCategoryOnly) { |
| 617 const std::string kJsonStr = | 736 const std::string kJsonStr = |
| 618 "{\"categories\" : [{" | 737 "{\"categories\" : [{" |
| 619 " \"id\": 1," | 738 " \"id\": 1," |
| 620 " \"localizedTitle\": \"Articles for You\"," | 739 " \"localizedTitle\": \"Articles for You\"," |
| 621 " \"suggestions\" : [{" | 740 " \"suggestions\" : [{" |
| 622 " \"ids\" : [\"http://localhost/foobar\"]," | 741 " \"ids\" : [\"http://localhost/foobar\"]," |
| 623 " \"title\" : \"Foo Barred from Baz\"," | 742 " \"title\" : \"Foo Barred from Baz\"," |
| 624 " \"snippet\" : \"...\"," | 743 " \"snippet\" : \"...\"," |
| 625 " \"fullPageUrl\" : \"http://localhost/foobar\"," | 744 " \"fullPageUrl\" : \"http://localhost/foobar\"," |
| 626 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," | 745 " \"creationTime\" : \"2016-06-30T11:01:37.000Z\"," |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 783 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 665 net::URLRequestStatus::SUCCESS); | 784 net::URLRequestStatus::SUCCESS); |
| 666 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories; | 785 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories; |
| 667 EXPECT_CALL(mock_callback(), Run(IsSuccess(), _)) | 786 EXPECT_CALL(mock_callback(), Run(IsSuccess(), _)) |
| 668 .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); | 787 .WillOnce(MoveArgument1PointeeTo(&fetched_categories)); |
| 669 | 788 |
| 670 RequestParams params = test_params(); | 789 RequestParams params = test_params(); |
| 671 params.exclusive_category = | 790 params.exclusive_category = |
| 672 base::Optional<Category>(Category::FromRemoteCategory(2)); | 791 base::Optional<Category>(Category::FromRemoteCategory(2)); |
| 673 | 792 |
| 674 snippets_fetcher().FetchSnippets( | 793 fetcher().FetchSnippets(params, |
| 675 params, ToSnippetsAvailableCallback(&mock_callback())); | 794 ToSnippetsAvailableCallback(&mock_callback())); |
| 676 FastForwardUntilNoTasksRemain(); | 795 FastForwardUntilNoTasksRemain(); |
| 677 | 796 |
| 678 ASSERT_TRUE(fetched_categories); | 797 ASSERT_TRUE(fetched_categories); |
| 679 ASSERT_THAT(fetched_categories->size(), Eq(1u)); | 798 ASSERT_THAT(fetched_categories->size(), Eq(1u)); |
| 680 const auto& category = (*fetched_categories)[0]; | 799 const auto& category = (*fetched_categories)[0]; |
| 681 EXPECT_THAT(category.category.id(), Eq(Category::FromRemoteCategory(2).id())); | 800 EXPECT_THAT(category.category.id(), Eq(Category::FromRemoteCategory(2).id())); |
| 682 ASSERT_THAT(category.suggestions.size(), Eq(1u)); | 801 ASSERT_THAT(category.suggestions.size(), Eq(1u)); |
| 683 EXPECT_THAT(category.suggestions[0]->url().spec(), | 802 EXPECT_THAT(category.suggestions[0]->url().spec(), |
| 684 Eq("http://localhost/foo2")); | 803 Eq("http://localhost/foo2")); |
| 685 } | 804 } |
| 686 | 805 |
| 687 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldFetchSuccessfullyEmptyList) { | 806 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, |
| 807 ShouldFetchSuccessfullyEmptyList) { |
| 688 const std::string kJsonStr = "{\"recos\": []}"; | 808 const std::string kJsonStr = "{\"recos\": []}"; |
| 689 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 809 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 690 net::URLRequestStatus::SUCCESS); | 810 net::URLRequestStatus::SUCCESS); |
| 691 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())); | 811 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())); |
| 692 snippets_fetcher().FetchSnippets( | 812 fetcher().FetchSnippets(test_params(), |
| 693 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 813 ToSnippetsAvailableCallback(&mock_callback())); |
| 694 FastForwardUntilNoTasksRemain(); | 814 FastForwardUntilNoTasksRemain(); |
| 695 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); | 815 EXPECT_THAT(fetcher().last_status(), Eq("OK")); |
| 696 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 816 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 697 EXPECT_THAT( | 817 EXPECT_THAT( |
| 698 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 818 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 699 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); | 819 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); |
| 700 EXPECT_THAT(histogram_tester().GetAllSamples( | 820 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 701 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 821 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 702 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 822 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 703 } | 823 } |
| 704 | 824 |
| 705 TEST_F(ChromeReaderSnippetsFetcherTest, RetryOnInteractiveRequests) { | 825 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, RetryOnInteractiveRequests) { |
| 706 DelegateCallingTestURLFetcherFactory fetcher_factory; | 826 DelegateCallingTestURLFetcherFactory fetcher_factory; |
| 707 RequestParams params = test_params(); | 827 RequestParams params = test_params(); |
| 708 params.interactive_request = true; | 828 params.interactive_request = true; |
| 709 | 829 |
| 710 snippets_fetcher().FetchSnippets( | 830 fetcher().FetchSnippets(params, |
| 711 params, ToSnippetsAvailableCallback(&mock_callback())); | 831 ToSnippetsAvailableCallback(&mock_callback())); |
| 712 | 832 |
| 713 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); | 833 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); |
| 714 ASSERT_THAT(fetcher, NotNull()); | 834 ASSERT_THAT(fetcher, NotNull()); |
| 715 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(2)); | 835 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(2)); |
| 716 } | 836 } |
| 717 | 837 |
| 718 TEST_F(ChromeReaderSnippetsFetcherTest, | 838 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, |
| 719 RetriesConfigurableOnNonInteractiveRequests) { | 839 RetriesConfigurableOnNonInteractiveRequests) { |
| 720 struct ExpectationForVariationParam { | 840 struct ExpectationForVariationParam { |
| 721 std::string param_value; | 841 std::string param_value; |
| 722 int expected_value; | 842 int expected_value; |
| 723 std::string description; | 843 std::string description; |
| 724 }; | 844 }; |
| 725 const std::vector<ExpectationForVariationParam> retry_config_expectation = { | 845 const std::vector<ExpectationForVariationParam> retry_config_expectation = { |
| 726 {"", 0, "Do not retry by default"}, | 846 {"", 0, "Do not retry by default"}, |
| 727 {"0", 0, "Do not retry on param value 0"}, | 847 {"0", 0, "Do not retry on param value 0"}, |
| 728 {"-1", 0, "Do not retry on negative param values."}, | 848 {"-1", 0, "Do not retry on negative param values."}, |
| 729 {"4", 4, "Retry as set in param value."}}; | 849 {"4", 4, "Retry as set in param value."}}; |
| 730 | 850 |
| 731 RequestParams params = test_params(); | 851 RequestParams params = test_params(); |
| 732 params.interactive_request = false; | 852 params.interactive_request = false; |
| 733 | 853 |
| 734 for (const auto& retry_config : retry_config_expectation) { | 854 for (const auto& retry_config : retry_config_expectation) { |
| 735 DelegateCallingTestURLFetcherFactory fetcher_factory; | 855 DelegateCallingTestURLFetcherFactory fetcher_factory; |
| 736 SetVariationParam("background_5xx_retries_count", retry_config.param_value); | 856 SetVariationParam("background_5xx_retries_count", retry_config.param_value); |
| 737 | 857 |
| 738 snippets_fetcher().FetchSnippets( | 858 fetcher().FetchSnippets(params, |
| 739 params, ToSnippetsAvailableCallback(&mock_callback())); | 859 ToSnippetsAvailableCallback(&mock_callback())); |
| 740 | 860 |
| 741 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); | 861 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher(); |
| 742 ASSERT_THAT(fetcher, NotNull()); | 862 ASSERT_THAT(fetcher, NotNull()); |
| 743 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(retry_config.expected_value)) | 863 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(retry_config.expected_value)) |
| 744 << retry_config.description; | 864 << retry_config.description; |
| 745 } | 865 } |
| 746 } | 866 } |
| 747 | 867 |
| 748 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldReportUrlStatusError) { | 868 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportUrlStatusError) { |
| 749 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, | 869 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, |
| 750 net::URLRequestStatus::FAILED); | 870 net::URLRequestStatus::FAILED); |
| 751 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 871 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 752 /*snippets=*/Not(HasValue()))) | 872 /*snippets=*/Not(HasValue()))) |
| 753 .Times(1); | 873 .Times(1); |
| 754 snippets_fetcher().FetchSnippets( | 874 fetcher().FetchSnippets(test_params(), |
| 755 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 875 ToSnippetsAvailableCallback(&mock_callback())); |
| 756 FastForwardUntilNoTasksRemain(); | 876 FastForwardUntilNoTasksRemain(); |
| 757 EXPECT_THAT(snippets_fetcher().last_status(), | 877 EXPECT_THAT(fetcher().last_status(), Eq("URLRequestStatus error -2")); |
| 758 Eq("URLRequestStatus error -2")); | 878 EXPECT_THAT(fetcher().last_json(), IsEmpty()); |
| 759 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); | |
| 760 EXPECT_THAT( | 879 EXPECT_THAT( |
| 761 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 880 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 762 ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); | 881 ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); |
| 763 EXPECT_THAT(histogram_tester().GetAllSamples( | 882 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 764 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 883 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 765 ElementsAre(base::Bucket(/*min=*/-2, /*count=*/1))); | 884 ElementsAre(base::Bucket(/*min=*/-2, /*count=*/1))); |
| 766 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 885 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 767 Not(IsEmpty())); | 886 Not(IsEmpty())); |
| 768 } | 887 } |
| 769 | 888 |
| 770 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldReportHttpError) { | 889 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportHttpError) { |
| 771 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, | 890 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, |
| 772 net::URLRequestStatus::SUCCESS); | 891 net::URLRequestStatus::SUCCESS); |
| 773 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 892 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 774 /*snippets=*/Not(HasValue()))) | 893 /*snippets=*/Not(HasValue()))) |
| 775 .Times(1); | 894 .Times(1); |
| 776 snippets_fetcher().FetchSnippets( | 895 fetcher().FetchSnippets(test_params(), |
| 777 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 896 ToSnippetsAvailableCallback(&mock_callback())); |
| 778 FastForwardUntilNoTasksRemain(); | 897 FastForwardUntilNoTasksRemain(); |
| 779 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); | 898 EXPECT_THAT(fetcher().last_json(), IsEmpty()); |
| 780 EXPECT_THAT( | 899 EXPECT_THAT( |
| 781 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 900 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 782 ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); | 901 ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); |
| 783 EXPECT_THAT(histogram_tester().GetAllSamples( | 902 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 784 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 903 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 785 ElementsAre(base::Bucket(/*min=*/404, /*count=*/1))); | 904 ElementsAre(base::Bucket(/*min=*/404, /*count=*/1))); |
| 786 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 905 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 787 Not(IsEmpty())); | 906 Not(IsEmpty())); |
| 788 } | 907 } |
| 789 | 908 |
| 790 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldReportJsonError) { | 909 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportJsonError) { |
| 791 const std::string kInvalidJsonStr = "{ \"recos\": []"; | 910 const std::string kInvalidJsonStr = "{ \"recos\": []"; |
| 792 SetFakeResponse(/*response_data=*/kInvalidJsonStr, net::HTTP_OK, | 911 SetFakeResponse(/*response_data=*/kInvalidJsonStr, net::HTTP_OK, |
| 793 net::URLRequestStatus::SUCCESS); | 912 net::URLRequestStatus::SUCCESS); |
| 794 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 913 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 795 /*snippets=*/Not(HasValue()))) | 914 /*snippets=*/Not(HasValue()))) |
| 796 .Times(1); | 915 .Times(1); |
| 797 snippets_fetcher().FetchSnippets( | 916 fetcher().FetchSnippets(test_params(), |
| 798 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 917 ToSnippetsAvailableCallback(&mock_callback())); |
| 799 FastForwardUntilNoTasksRemain(); | 918 FastForwardUntilNoTasksRemain(); |
| 800 EXPECT_THAT(snippets_fetcher().last_status(), | 919 EXPECT_THAT(fetcher().last_status(), |
| 801 StartsWith("Received invalid JSON (error ")); | 920 StartsWith("Received invalid JSON (error ")); |
| 802 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kInvalidJsonStr)); | 921 EXPECT_THAT(fetcher().last_json(), Eq(kInvalidJsonStr)); |
| 803 EXPECT_THAT( | 922 EXPECT_THAT( |
| 804 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 923 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 805 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); | 924 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); |
| 806 EXPECT_THAT(histogram_tester().GetAllSamples( | 925 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 807 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 926 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 808 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 927 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 809 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 928 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 810 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | 929 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 811 /*count=*/1))); | 930 /*count=*/1))); |
| 812 } | 931 } |
| 813 | 932 |
| 814 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldReportJsonErrorForEmptyResponse) { | 933 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, |
| 934 ShouldReportJsonErrorForEmptyResponse) { |
| 815 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_OK, | 935 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_OK, |
| 816 net::URLRequestStatus::SUCCESS); | 936 net::URLRequestStatus::SUCCESS); |
| 817 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 937 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 818 /*snippets=*/Not(HasValue()))) | 938 /*snippets=*/Not(HasValue()))) |
| 819 .Times(1); | 939 .Times(1); |
| 820 snippets_fetcher().FetchSnippets( | 940 fetcher().FetchSnippets(test_params(), |
| 821 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 941 ToSnippetsAvailableCallback(&mock_callback())); |
| 822 FastForwardUntilNoTasksRemain(); | 942 FastForwardUntilNoTasksRemain(); |
| 823 EXPECT_THAT(snippets_fetcher().last_json(), std::string()); | 943 EXPECT_THAT(fetcher().last_json(), std::string()); |
| 824 EXPECT_THAT( | 944 EXPECT_THAT( |
| 825 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 945 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 826 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); | 946 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); |
| 827 EXPECT_THAT(histogram_tester().GetAllSamples( | 947 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 828 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 948 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 829 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 949 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 830 } | 950 } |
| 831 | 951 |
| 832 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldReportInvalidListError) { | 952 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, ShouldReportInvalidListError) { |
| 833 const std::string kJsonStr = | 953 const std::string kJsonStr = |
| 834 "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}"; | 954 "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}"; |
| 835 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 955 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 836 net::URLRequestStatus::SUCCESS); | 956 net::URLRequestStatus::SUCCESS); |
| 837 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 957 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 838 /*snippets=*/Not(HasValue()))) | 958 /*snippets=*/Not(HasValue()))) |
| 839 .Times(1); | 959 .Times(1); |
| 840 snippets_fetcher().FetchSnippets( | 960 fetcher().FetchSnippets(test_params(), |
| 841 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 961 ToSnippetsAvailableCallback(&mock_callback())); |
| 842 FastForwardUntilNoTasksRemain(); | 962 FastForwardUntilNoTasksRemain(); |
| 843 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 963 EXPECT_THAT(fetcher().last_json(), Eq(kJsonStr)); |
| 844 EXPECT_THAT( | 964 EXPECT_THAT( |
| 845 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 965 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 846 ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); | 966 ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); |
| 847 EXPECT_THAT(histogram_tester().GetAllSamples( | 967 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 848 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 968 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 849 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 969 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 850 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 970 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 851 Not(IsEmpty())); | 971 Not(IsEmpty())); |
| 852 } | 972 } |
| 853 | 973 |
| 854 // This test actually verifies that the test setup itself is sane, to prevent | 974 // This test actually verifies that the test setup itself is sane, to prevent |
| 855 // hard-to-reproduce test failures. | 975 // hard-to-reproduce test failures. |
| 856 TEST_F(ChromeReaderSnippetsFetcherTest, | 976 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, |
| 857 ShouldReportHttpErrorForMissingBakedResponse) { | 977 ShouldReportHttpErrorForMissingBakedResponse) { |
| 858 InitFakeURLFetcherFactory(); | 978 InitFakeURLFetcherFactory(); |
| 859 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), | 979 EXPECT_CALL(mock_callback(), Run(HasCode(StatusCode::TEMPORARY_ERROR), |
| 860 /*snippets=*/Not(HasValue()))) | 980 /*snippets=*/Not(HasValue()))) |
| 861 .Times(1); | 981 .Times(1); |
| 862 snippets_fetcher().FetchSnippets( | 982 fetcher().FetchSnippets(test_params(), |
| 863 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 983 ToSnippetsAvailableCallback(&mock_callback())); |
| 864 FastForwardUntilNoTasksRemain(); | 984 FastForwardUntilNoTasksRemain(); |
| 865 } | 985 } |
| 866 | 986 |
| 867 TEST_F(ChromeReaderSnippetsFetcherTest, ShouldProcessConcurrentFetches) { | 987 TEST_F(RemoteSuggestionsChromeReaderFetcherTest, |
| 988 ShouldProcessConcurrentFetches) { |
| 868 const std::string kJsonStr = "{ \"recos\": [] }"; | 989 const std::string kJsonStr = "{ \"recos\": [] }"; |
| 869 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, | 990 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, |
| 870 net::URLRequestStatus::SUCCESS); | 991 net::URLRequestStatus::SUCCESS); |
| 871 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())).Times(5); | 992 EXPECT_CALL(mock_callback(), Run(IsSuccess(), IsEmptyArticleList())).Times(5); |
| 872 snippets_fetcher().FetchSnippets( | 993 fetcher().FetchSnippets(test_params(), |
| 873 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 994 ToSnippetsAvailableCallback(&mock_callback())); |
| 874 // More calls to FetchSnippets() do not interrupt the previous. | 995 // More calls to FetchSnippets() do not interrupt the previous. |
| 875 // Callback is expected to be called once each time. | 996 // Callback is expected to be called once each time. |
| 876 snippets_fetcher().FetchSnippets( | 997 fetcher().FetchSnippets(test_params(), |
| 877 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 998 ToSnippetsAvailableCallback(&mock_callback())); |
| 878 snippets_fetcher().FetchSnippets( | 999 fetcher().FetchSnippets(test_params(), |
| 879 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 1000 ToSnippetsAvailableCallback(&mock_callback())); |
| 880 snippets_fetcher().FetchSnippets( | 1001 fetcher().FetchSnippets(test_params(), |
| 881 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 1002 ToSnippetsAvailableCallback(&mock_callback())); |
| 882 snippets_fetcher().FetchSnippets( | 1003 fetcher().FetchSnippets(test_params(), |
| 883 test_params(), ToSnippetsAvailableCallback(&mock_callback())); | 1004 ToSnippetsAvailableCallback(&mock_callback())); |
| 884 FastForwardUntilNoTasksRemain(); | 1005 FastForwardUntilNoTasksRemain(); |
| 885 EXPECT_THAT( | 1006 EXPECT_THAT( |
| 886 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 1007 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 887 ElementsAre(base::Bucket(/*min=*/0, /*count=*/5))); | 1008 ElementsAre(base::Bucket(/*min=*/0, /*count=*/5))); |
| 888 EXPECT_THAT(histogram_tester().GetAllSamples( | 1009 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 889 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 1010 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 890 ElementsAre(base::Bucket(/*min=*/200, /*count=*/5))); | 1011 ElementsAre(base::Bucket(/*min=*/200, /*count=*/5))); |
| 891 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), | 1012 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 892 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, | 1013 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 893 /*count=*/5))); | 1014 /*count=*/5))); |
| 894 } | 1015 } |
| 895 | 1016 |
| 896 ::std::ostream& operator<<( | 1017 ::std::ostream& operator<<( |
| 897 ::std::ostream& os, | 1018 ::std::ostream& os, |
| 898 const RemoteSuggestionsFetcher::OptionalFetchedCategories& | 1019 const RemoteSuggestionsFetcher::OptionalFetchedCategories& |
| 899 fetched_categories) { | 1020 fetched_categories) { |
| 900 if (fetched_categories) { | 1021 if (fetched_categories) { |
| 901 // Matchers above aren't any more precise than this, so this is sufficient | 1022 // Matchers above aren't any more precise than this, so this is sufficient |
| 902 // for test-failure diagnostics. | 1023 // for test-failure diagnostics. |
| 903 return os << "list with " << fetched_categories->size() << " elements"; | 1024 return os << "list with " << fetched_categories->size() << " elements"; |
| 904 } | 1025 } |
| 905 return os << "null"; | 1026 return os << "null"; |
| 906 } | 1027 } |
| 907 | 1028 |
| 908 } // namespace ntp_snippets | 1029 } // namespace ntp_snippets |
| OLD | NEW |