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

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

Issue 2548343002: NTPSnippets: Set MaxRetriesOn5xx only for interactive requests. (Closed)
Patch Set: Replaced inherited test with scope-injected fetcher. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 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/ntp_snippets_fetcher.h" 5 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h"
6 6
7 #include <map> 7 #include <map>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 class RequestBuilderWithMockedFlagsForTesting 202 class RequestBuilderWithMockedFlagsForTesting
203 : public NTPSnippetsFetcher::RequestBuilder { 203 : public NTPSnippetsFetcher::RequestBuilder {
204 public: 204 public:
205 RequestBuilderWithMockedFlagsForTesting() : RequestBuilder() {} 205 RequestBuilderWithMockedFlagsForTesting() : RequestBuilder() {}
206 206
207 private: 207 private:
208 bool IsSendingUserClassEnabled() const override { return true; } 208 bool IsSendingUserClassEnabled() const override { return true; }
209 bool IsSendingTopLanguagesEnabled() const override { return true; } 209 bool IsSendingTopLanguagesEnabled() const override { return true; }
210 }; 210 };
211 211
212 class ScopedInjectedTestURLFetcherFactory {
tschumann 2016/12/08 13:27:53 now that I better understand the usage pattern, ma
fhorschig 2016/12/09 12:37:55 Moved. Commented. It is now a Factory itself and i
213 public:
214 ScopedInjectedTestURLFetcherFactory() {}
215 ~ScopedInjectedTestURLFetcherFactory() {
216 net::TestURLFetcher* fetcher = GetLastCreatedUrlFetcher();
tschumann 2016/12/08 13:27:53 either clearly document that we only support creat
fhorschig 2016/12/09 12:37:55 We support now creation of multiple fetchers [1],
217 if (fetcher) {
218 // An 4XX response needs the least configuration to successfully invoke
219 // the callback properly.
220 fetcher->set_response_code(net::HTTP_NOT_FOUND);
221 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED,
222 net::ERR_FAILED));
223 fetcher->delegate()->OnURLFetchComplete(fetcher);
224 test_url_fetcher_factory_.RemoveFetcherFromMap(0);
225 }
226 }
227
228 net::TestURLFetcher* GetLastCreatedUrlFetcher() const {
229 // If there is a fetcher, the first fetcher is always at 0.
230 // If there is no fetcher, the resulting pointer will be nulltpr, no
231 // matter
232 // which index was used.
Marc Treib 2016/12/08 10:52:06 nit: some extra newlines here
fhorschig 2016/12/09 12:37:55 Done.
233 // If you try to access another fetcher, the old fetcher must be destroyed
234 // manuall first (by calling |CloseLastUrlFetcher|) in order to secure
Marc Treib 2016/12/08 10:52:06 s/manuall/manually/
fhorschig 2016/12/09 12:37:55 Done.
235 // that
236 // the delegate was called. This wouldn't happen by default and would leak
237 // a once-bound SnippetsAvailableCallback.
238 return test_url_fetcher_factory_.GetFetcherByID(0);
239 }
240
241 private:
242 net::TestURLFetcherFactory test_url_fetcher_factory_;
243 };
244
212 NTPSnippetsFetcherTest() 245 NTPSnippetsFetcherTest()
213 : NTPSnippetsFetcherTest(GURL(kTestChromeReaderUrl), 246 : NTPSnippetsFetcherTest(GURL(kTestChromeReaderUrl),
214 std::map<std::string, std::string>()) {} 247 std::map<std::string, std::string>()) {}
215 248
216 NTPSnippetsFetcherTest(const GURL& gurl, 249 NTPSnippetsFetcherTest(const GURL& gurl,
217 const std::map<std::string, std::string>& params) 250 const std::map<std::string, std::string>& params)
218 : params_manager_( 251 : params_manager_(
219 base::MakeUnique<variations::testing::VariationParamsManager>( 252 base::MakeUnique<variations::testing::VariationParamsManager>(
220 ntp_snippets::kStudyName, 253 ntp_snippets::kStudyName,
221 params)), 254 params)),
(...skipping 21 matching lines...) Expand all
243 fake_signin_manager_.get(), fake_token_service_.get(), 276 fake_signin_manager_.get(), fake_token_service_.get(),
244 scoped_refptr<net::TestURLRequestContextGetter>( 277 scoped_refptr<net::TestURLRequestContextGetter>(
245 new net::TestURLRequestContextGetter(mock_task_runner_.get())), 278 new net::TestURLRequestContextGetter(mock_task_runner_.get())),
246 pref_service_.get(), &category_factory_, nullptr, 279 pref_service_.get(), &category_factory_, nullptr,
247 base::Bind(&ParseJsonDelayed), kAPIKey, user_classifier_.get()); 280 base::Bind(&ParseJsonDelayed), kAPIKey, user_classifier_.get());
248 281
249 snippets_fetcher_->SetTickClockForTesting( 282 snippets_fetcher_->SetTickClockForTesting(
250 mock_task_runner_->GetMockTickClock()); 283 mock_task_runner_->GetMockTickClock());
251 } 284 }
252 285
286 NTPSnippetsFetcher::SnippetsAvailableCallback
287 CreateSnippetsAvailableCallback() {
288 // Make sure the callback gets executed.
289 EXPECT_CALL(mock_callback(), Run(/*snippets=*/_)).Times(1);
290 return ToSnippetsAvailableCallback(&mock_callback());
Marc Treib 2016/12/08 10:52:06 Hm, how about inlining this into the tests themsel
tschumann 2016/12/08 13:27:53 +1
fhorschig 2016/12/09 12:37:55 Removed. As they cannot happen anymore with the de
291 }
292
253 NTPSnippetsFetcher::SnippetsAvailableCallback ToSnippetsAvailableCallback( 293 NTPSnippetsFetcher::SnippetsAvailableCallback ToSnippetsAvailableCallback(
254 MockSnippetsAvailableCallback* callback) { 294 MockSnippetsAvailableCallback* callback) {
255 return base::BindOnce(&MockSnippetsAvailableCallback::WrappedRun, 295 return base::BindOnce(&MockSnippetsAvailableCallback::WrappedRun,
256 base::Unretained(callback)); 296 base::Unretained(callback));
257 } 297 }
258 298
259 NTPSnippetsFetcher& snippets_fetcher() { return *snippets_fetcher_; } 299 NTPSnippetsFetcher& snippets_fetcher() { return *snippets_fetcher_; }
260 MockSnippetsAvailableCallback& mock_callback() { return mock_callback_; } 300 MockSnippetsAvailableCallback& mock_callback() { return mock_callback_; }
261 void FastForwardUntilNoTasksRemain() { 301 void FastForwardUntilNoTasksRemain() {
262 mock_task_runner_->FastForwardUntilNoTasksRemain(); 302 mock_task_runner_->FastForwardUntilNoTasksRemain();
(...skipping 10 matching lines...) Expand all
273 void InitFakeURLFetcherFactory() { 313 void InitFakeURLFetcherFactory() {
274 if (fake_url_fetcher_factory_) { 314 if (fake_url_fetcher_factory_) {
275 return; 315 return;
276 } 316 }
277 // Instantiation of factory automatically sets itself as URLFetcher's 317 // Instantiation of factory automatically sets itself as URLFetcher's
278 // factory. 318 // factory.
279 fake_url_fetcher_factory_.reset(new net::FakeURLFetcherFactory( 319 fake_url_fetcher_factory_.reset(new net::FakeURLFetcherFactory(
280 /*default_factory=*/&failing_url_fetcher_factory_)); 320 /*default_factory=*/&failing_url_fetcher_factory_));
281 } 321 }
282 322
283 void SetFetchingPersonalizationVariation( 323 void SetVariationParameters(
284 const std::string& personalization_string) { 324 const std::map<std::string, std::string>& params) {
285 params_manager_.reset(); 325 params_manager_.reset();
286 std::map<std::string, std::string> params = {
287 {"fetching_personalization", personalization_string}};
288 params_manager_ = 326 params_manager_ =
289 base::MakeUnique<variations::testing::VariationParamsManager>( 327 base::MakeUnique<variations::testing::VariationParamsManager>(
290 ntp_snippets::kStudyName, params); 328 ntp_snippets::kStudyName, params);
291 } 329 }
292 330
293 void SetFakeResponse(const std::string& response_data, 331 void SetFakeResponse(const std::string& response_data,
294 net::HttpStatusCode response_code, 332 net::HttpStatusCode response_code,
295 net::URLRequestStatus::Status status) { 333 net::URLRequestStatus::Status status) {
296 InitFakeURLFetcherFactory(); 334 InitFakeURLFetcherFactory();
297 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data, 335 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data,
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 Eq(CategoryFactory().FromRemoteCategory(2).id())); 903 Eq(CategoryFactory().FromRemoteCategory(2).id()));
866 ASSERT_THAT(category.snippets.size(), Eq(1u)); 904 ASSERT_THAT(category.snippets.size(), Eq(1u));
867 EXPECT_THAT(category.snippets[0]->url().spec(), Eq("http://localhost/foo2")); 905 EXPECT_THAT(category.snippets[0]->url().spec(), Eq("http://localhost/foo2"));
868 } 906 }
869 907
870 TEST_F(NTPSnippetsFetcherTest, PersonalizesDependingOnVariations) { 908 TEST_F(NTPSnippetsFetcherTest, PersonalizesDependingOnVariations) {
871 // Default setting should be both personalization options. 909 // Default setting should be both personalization options.
872 EXPECT_THAT(snippets_fetcher().personalization(), 910 EXPECT_THAT(snippets_fetcher().personalization(),
873 Eq(NTPSnippetsFetcher::Personalization::kBoth)); 911 Eq(NTPSnippetsFetcher::Personalization::kBoth));
874 912
875 SetFetchingPersonalizationVariation("personal"); 913 SetVariationParameters({{"fetching_personalization", "personal"}});
876 ResetSnippetsFetcher(); 914 ResetSnippetsFetcher();
877 EXPECT_THAT(snippets_fetcher().personalization(), 915 EXPECT_THAT(snippets_fetcher().personalization(),
878 Eq(NTPSnippetsFetcher::Personalization::kPersonal)); 916 Eq(NTPSnippetsFetcher::Personalization::kPersonal));
879 917
880 SetFetchingPersonalizationVariation("non_personal"); 918 SetVariationParameters({{"fetching_personalization", "non_personal"}});
881 ResetSnippetsFetcher(); 919 ResetSnippetsFetcher();
882 EXPECT_THAT(snippets_fetcher().personalization(), 920 EXPECT_THAT(snippets_fetcher().personalization(),
883 Eq(NTPSnippetsFetcher::Personalization::kNonPersonal)); 921 Eq(NTPSnippetsFetcher::Personalization::kNonPersonal));
884 922
885 SetFetchingPersonalizationVariation("both"); 923 SetVariationParameters({{"fetching_personalization", "both"}});
886 ResetSnippetsFetcher(); 924 ResetSnippetsFetcher();
887 EXPECT_THAT(snippets_fetcher().personalization(), 925 EXPECT_THAT(snippets_fetcher().personalization(),
888 Eq(NTPSnippetsFetcher::Personalization::kBoth)); 926 Eq(NTPSnippetsFetcher::Personalization::kBoth));
889 } 927 }
890 928
891 TEST_F(NTPSnippetsFetcherTest, ShouldFetchSuccessfullyEmptyList) { 929 TEST_F(NTPSnippetsFetcherTest, ShouldFetchSuccessfullyEmptyList) {
892 const std::string kJsonStr = "{\"recos\": []}"; 930 const std::string kJsonStr = "{\"recos\": []}";
893 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK, 931 SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
894 net::URLRequestStatus::SUCCESS); 932 net::URLRequestStatus::SUCCESS);
895 EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList())); 933 EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList()));
896 snippets_fetcher().FetchSnippets( 934 snippets_fetcher().FetchSnippets(
897 test_params(), ToSnippetsAvailableCallback(&mock_callback())); 935 test_params(), ToSnippetsAvailableCallback(&mock_callback()));
898 FastForwardUntilNoTasksRemain(); 936 FastForwardUntilNoTasksRemain();
899 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); 937 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK"));
900 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); 938 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr));
901 EXPECT_THAT( 939 EXPECT_THAT(
902 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), 940 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"),
903 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); 941 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1)));
904 EXPECT_THAT(histogram_tester().GetAllSamples( 942 EXPECT_THAT(histogram_tester().GetAllSamples(
905 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), 943 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"),
906 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); 944 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1)));
907 } 945 }
908 946
909 TEST_F(NTPSnippetsFetcherTest, ShouldRestrictToHosts) { 947 TEST_F(NTPSnippetsFetcherTest, ShouldRestrictToHosts) {
910 net::TestURLFetcherFactory test_url_fetcher_factory;
911 NTPSnippetsFetcher::Params params = test_params(); 948 NTPSnippetsFetcher::Params params = test_params();
912 params.hosts = {"www.somehost1.com", "www.somehost2.com"}; 949 params.hosts = {"www.somehost1.com", "www.somehost2.com"};
913 params.count_to_fetch = 17; 950 params.count_to_fetch = 17;
914 snippets_fetcher().FetchSnippets( 951 std::unique_ptr<base::Value> value;
915 params, ToSnippetsAvailableCallback(&mock_callback())); 952 {
916 net::TestURLFetcher* fetcher = test_url_fetcher_factory.GetFetcherByID(0); 953 ScopedInjectedTestURLFetcherFactory url_fetcher_factory;
917 ASSERT_THAT(fetcher, NotNull()); 954 snippets_fetcher().FetchSnippets(params, CreateSnippetsAvailableCallback());
918 std::unique_ptr<base::Value> value = 955
919 base::JSONReader::Read(fetcher->upload_data()); 956 net::TestURLFetcher* fetcher =
920 ASSERT_TRUE(value) << " failed to parse JSON: " 957 url_fetcher_factory.GetLastCreatedUrlFetcher();
921 << PrintToString(fetcher->upload_data()); 958 ASSERT_THAT(fetcher, NotNull());
959 value = base::JSONReader::Read(fetcher->upload_data());
960 ASSERT_TRUE(value) << " failed to parse JSON: "
961 << PrintToString(fetcher->upload_data());
962 }
922 const base::DictionaryValue* dict = nullptr; 963 const base::DictionaryValue* dict = nullptr;
923 ASSERT_TRUE(value->GetAsDictionary(&dict)); 964 ASSERT_TRUE(value->GetAsDictionary(&dict));
924 const base::DictionaryValue* local_scoring_params = nullptr; 965 const base::DictionaryValue* local_scoring_params = nullptr;
925 ASSERT_TRUE(dict->GetDictionary("advanced_options.local_scoring_params", 966 ASSERT_TRUE(dict->GetDictionary("advanced_options.local_scoring_params",
926 &local_scoring_params)); 967 &local_scoring_params));
927 const base::ListValue* content_selectors = nullptr; 968 const base::ListValue* content_selectors = nullptr;
928 ASSERT_TRUE( 969 ASSERT_TRUE(
929 local_scoring_params->GetList("content_selectors", &content_selectors)); 970 local_scoring_params->GetList("content_selectors", &content_selectors));
930 ASSERT_THAT(content_selectors->GetSize(), Eq(static_cast<size_t>(2))); 971 ASSERT_THAT(content_selectors->GetSize(), Eq(static_cast<size_t>(2)));
931 const base::DictionaryValue* content_selector = nullptr; 972 const base::DictionaryValue* content_selector = nullptr;
932 ASSERT_TRUE(content_selectors->GetDictionary(0, &content_selector)); 973 ASSERT_TRUE(content_selectors->GetDictionary(0, &content_selector));
933 std::string content_selector_value; 974 std::string content_selector_value;
934 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value)); 975 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value));
935 EXPECT_THAT(content_selector_value, Eq("www.somehost1.com")); 976 EXPECT_THAT(content_selector_value, Eq("www.somehost1.com"));
936 ASSERT_TRUE(content_selectors->GetDictionary(1, &content_selector)); 977 ASSERT_TRUE(content_selectors->GetDictionary(1, &content_selector));
937 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value)); 978 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value));
938 EXPECT_THAT(content_selector_value, Eq("www.somehost2.com")); 979 EXPECT_THAT(content_selector_value, Eq("www.somehost2.com"));
939 // Call the delegate callback manually as the TestURLFetcher deletes any 980 }
940 // call to the delegate that usually happens on |Start|. 981
941 // Without the call to the delegate, it leaks the request that owns itself. 982 TEST_F(NTPSnippetsFetcherTest, RetryOnInteractiveRequests) {
942 ASSERT_THAT(fetcher->delegate(), NotNull()); 983 NTPSnippetsFetcher::Params params = test_params();
943 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); 984 params.interactive_request = true;
944 // An 4XX response needs the least configuration to successfully invoke the 985 {
945 // callback properly as the results are not important in this test. 986 ScopedInjectedTestURLFetcherFactory url_fetcher_factory;
946 fetcher->set_response_code(net::HTTP_NOT_FOUND); 987 snippets_fetcher().FetchSnippets(params, CreateSnippetsAvailableCallback());
947 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, -2)); 988
948 fetcher->delegate()->OnURLFetchComplete(fetcher); 989 net::TestURLFetcher* fetcher =
990 url_fetcher_factory.GetLastCreatedUrlFetcher();
991 ASSERT_THAT(fetcher, NotNull());
992 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(2));
993 }
994 }
995
996 TEST_F(NTPSnippetsFetcherTest, RetriesConfigurableOnNonInteractiveRequests) {
997 NTPSnippetsFetcher::Params params = test_params();
998 params.interactive_request = false;
999 std::map<std::string, int> expected_retries_for_configurations = {
Marc Treib 2016/12/08 10:52:06 Make this const? I'd also slightly prefer an array
tschumann 2016/12/08 13:27:53 Using a struct would be better indeed -- you seem
Marc Treib 2016/12/08 13:31:56 Right, vector also works, now that we have std::in
fhorschig 2016/12/09 12:37:55 Done.
1000 {"", 0}, // Keep 2 retries if no variation is set.
1001 {"0", 0},
1002 {"-1", 0}, // Allow no negative retry count.
1003 {"3", 3}};
1004
1005 for (auto retry_configuration : expected_retries_for_configurations) {
Marc Treib 2016/12/08 10:52:06 const auto& ?
fhorschig 2016/12/09 12:37:55 Done.
1006 ScopedInjectedTestURLFetcherFactory url_fetcher_factory;
1007 SetVariationParameters(
1008 {{"number_of_non_interactive_5xx_retries", retry_configuration.first}});
1009
1010 snippets_fetcher().FetchSnippets(params, CreateSnippetsAvailableCallback());
1011
1012 net::TestURLFetcher* fetcher =
1013 url_fetcher_factory.GetLastCreatedUrlFetcher();
1014 ASSERT_THAT(fetcher, NotNull());
1015 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(retry_configuration.second));
1016 }
949 } 1017 }
950 1018
951 TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) { 1019 TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) {
952 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, 1020 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
953 net::URLRequestStatus::FAILED); 1021 net::URLRequestStatus::FAILED);
954 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); 1022 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
955 snippets_fetcher().FetchSnippets( 1023 snippets_fetcher().FetchSnippets(
956 test_params(), ToSnippetsAvailableCallback(&mock_callback())); 1024 test_params(), ToSnippetsAvailableCallback(&mock_callback()));
957 FastForwardUntilNoTasksRemain(); 1025 FastForwardUntilNoTasksRemain();
958 EXPECT_THAT(snippets_fetcher().last_status(), 1026 EXPECT_THAT(snippets_fetcher().last_status(),
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 const NTPSnippetsFetcher::OptionalFetchedCategories& fetched_categories) { 1156 const NTPSnippetsFetcher::OptionalFetchedCategories& fetched_categories) {
1089 if (fetched_categories) { 1157 if (fetched_categories) {
1090 // Matchers above aren't any more precise than this, so this is sufficient 1158 // Matchers above aren't any more precise than this, so this is sufficient
1091 // for test-failure diagnostics. 1159 // for test-failure diagnostics.
1092 return os << "list with " << fetched_categories->size() << " elements"; 1160 return os << "list with " << fetched_categories->size() << " elements";
1093 } 1161 }
1094 return os << "null"; 1162 return os << "null";
1095 } 1163 }
1096 1164
1097 } // namespace ntp_snippets 1165 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698