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

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: Document missing functionality inline. 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
« no previous file with comments | « components/ntp_snippets/remote/ntp_snippets_fetcher.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <deque>
7 #include <map> 8 #include <map>
8 #include <utility> 9 #include <utility>
9 10
10 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
11 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
12 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
13 #include "base/test/histogram_tester.h" 14 #include "base/test/histogram_tester.h"
14 #include "base/test/test_mock_time_task_runner.h" 15 #include "base/test/test_mock_time_task_runner.h"
15 #include "base/threading/thread_task_runner_handle.h" 16 #include "base/threading/thread_task_runner_handle.h"
16 #include "base/time/time.h" 17 #include "base/time/time.h"
17 #include "base/values.h" 18 #include "base/values.h"
18 #include "components/ntp_snippets/category_factory.h" 19 #include "components/ntp_snippets/category_factory.h"
20 #include "components/ntp_snippets/features.h"
19 #include "components/ntp_snippets/ntp_snippets_constants.h" 21 #include "components/ntp_snippets/ntp_snippets_constants.h"
20 #include "components/ntp_snippets/remote/ntp_snippet.h" 22 #include "components/ntp_snippets/remote/ntp_snippet.h"
21 #include "components/ntp_snippets/user_classifier.h" 23 #include "components/ntp_snippets/user_classifier.h"
22 #include "components/prefs/testing_pref_service.h" 24 #include "components/prefs/testing_pref_service.h"
23 #include "components/signin/core/browser/account_tracker_service.h" 25 #include "components/signin/core/browser/account_tracker_service.h"
24 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" 26 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
25 #include "components/signin/core/browser/fake_signin_manager.h" 27 #include "components/signin/core/browser/fake_signin_manager.h"
26 #include "components/signin/core/browser/test_signin_client.h" 28 #include "components/signin/core/browser/test_signin_client.h"
27 #include "components/variations/entropy_provider.h" 29 #include "components/variations/entropy_provider.h"
28 #include "components/variations/variations_params_manager.h" 30 #include "components/variations/variations_params_manager.h"
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) { 155 NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) {
154 Run(fetch_result, &fetched_categories); 156 Run(fetch_result, &fetched_categories);
155 } 157 }
156 158
157 MOCK_METHOD2( 159 MOCK_METHOD2(
158 Run, 160 Run,
159 void(NTPSnippetsFetcher::FetchResult fetch_result, 161 void(NTPSnippetsFetcher::FetchResult fetch_result,
160 NTPSnippetsFetcher::OptionalFetchedCategories* fetched_categories)); 162 NTPSnippetsFetcher::OptionalFetchedCategories* fetched_categories));
161 }; 163 };
162 164
165 // TODO(fhorschig): Transfer this class' functionality to call delegates
166 // automatically as option to TestURLFetcherFactory where it was just deleted.
167 // This can be represented as a single member there and would reduce the amount
168 // of fake implementations from three to two.
169
170 // DelegateCallingTestURLFetcherFactory can be used to temporarily inject
171 // TestURLFetcher instances into a scope.
172 // Client code can access the last created fetcher to verify expected
173 // properties. When the factory gets destroyed, all available delegates of still
174 // valid fetchers will be called.
175 // This ensures once-bound callbacks (like SnippetsAvailableCallback) will be
176 // called at some point and are not leaked.
177 class DelegateCallingTestURLFetcherFactory
178 : public net::TestURLFetcherFactory,
179 public net::TestURLFetcherDelegateForTests {
180 public:
181 DelegateCallingTestURLFetcherFactory() {
182 SetDelegateForTests(this);
183 set_remove_fetcher_on_delete(true);
184 }
185
186 ~DelegateCallingTestURLFetcherFactory() override {
187 while (!fetchers_.empty()) {
188 DropAndCallDelegate(fetchers_.front());
189 }
190 }
191
192 std::unique_ptr<net::URLFetcher> CreateURLFetcher(
193 int id,
194 const GURL& url,
195 net::URLFetcher::RequestType request_type,
196 net::URLFetcherDelegate* d) override {
197 if (GetFetcherByID(id)) {
198 LOG(WARNING) << "The ID " << id << " was already assigned to a fetcher."
199 << "Its delegate will thereforde be called right now.";
200 DropAndCallDelegate(id);
201 }
202 fetchers_.push_back(id);
203 return TestURLFetcherFactory::CreateURLFetcher(id, url, request_type, d);
204 }
205
206 // Returns the raw pointer of the last created URL fetcher.
207 // If it was destroyed or no fetcher was created, it will return a nulltpr.
208 net::TestURLFetcher* GetLastCreatedFetcher() {
209 if (fetchers_.empty()) {
210 return nullptr;
211 }
212 return GetFetcherByID(fetchers_.front());
213 }
214
215 private:
216 // The fetcher can either be destroyed because the delegate was called during
217 // execution or because we called it on destruction.
218 void DropAndCallDelegate(int fetcher_id) {
219 auto found_id_iter =
220 std::find(fetchers_.begin(), fetchers_.end(), fetcher_id);
221 if (found_id_iter == fetchers_.end()) {
222 return;
223 }
224 fetchers_.erase(found_id_iter);
225 net::TestURLFetcher* fetcher = GetFetcherByID(fetcher_id);
226 if (!fetcher->delegate()) {
227 return;
228 }
229 fetcher->delegate()->OnURLFetchComplete(fetcher);
230 }
231
232 // net::TestURLFetcherDelegateForTests overrides:
233 void OnRequestStart(int fetcher_id) override {}
234 void OnChunkUpload(int fetcher_id) override {}
235 void OnRequestEnd(int fetcher_id) override {
236 DropAndCallDelegate(fetcher_id);
237 }
238
239 std::deque<int> fetchers_; // std::queue doesn't support std::find.
240 };
241
163 // Factory for FakeURLFetcher objects that always generate errors. 242 // Factory for FakeURLFetcher objects that always generate errors.
164 class FailingFakeURLFetcherFactory : public net::URLFetcherFactory { 243 class FailingFakeURLFetcherFactory : public net::URLFetcherFactory {
165 public: 244 public:
166 std::unique_ptr<net::URLFetcher> CreateURLFetcher( 245 std::unique_ptr<net::URLFetcher> CreateURLFetcher(
167 int id, const GURL& url, net::URLFetcher::RequestType request_type, 246 int id, const GURL& url, net::URLFetcher::RequestType request_type,
168 net::URLFetcherDelegate* d) override { 247 net::URLFetcherDelegate* d) override {
169 return base::MakeUnique<net::FakeURLFetcher>( 248 return base::MakeUnique<net::FakeURLFetcher>(
170 url, d, /*response_data=*/std::string(), net::HTTP_NOT_FOUND, 249 url, d, /*response_data=*/std::string(), net::HTTP_NOT_FOUND,
171 net::URLRequestStatus::FAILED); 250 net::URLRequestStatus::FAILED);
172 } 251 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 void SetFetchingPersonalizationVariation( 364 void SetFetchingPersonalizationVariation(
286 const std::string& personalization_string) { 365 const std::string& personalization_string) {
287 params_manager_.reset(); 366 params_manager_.reset();
288 std::map<std::string, std::string> params = { 367 std::map<std::string, std::string> params = {
289 {"fetching_personalization", personalization_string}}; 368 {"fetching_personalization", personalization_string}};
290 params_manager_ = 369 params_manager_ =
291 base::MakeUnique<variations::testing::VariationParamsManager>( 370 base::MakeUnique<variations::testing::VariationParamsManager>(
292 ntp_snippets::kStudyName, params); 371 ntp_snippets::kStudyName, params);
293 } 372 }
294 373
374 void SetVariationParametersForFeatures(
375 const std::map<std::string, std::string>& params,
376 const std::set<std::string>& features) {
377 params_manager_.reset();
378 params_manager_ =
379 base::MakeUnique<variations::testing::VariationParamsManager>(
380 ntp_snippets::kStudyName, params, features);
381 }
382
295 void SetFakeResponse(const std::string& response_data, 383 void SetFakeResponse(const std::string& response_data,
296 net::HttpStatusCode response_code, 384 net::HttpStatusCode response_code,
297 net::URLRequestStatus::Status status) { 385 net::URLRequestStatus::Status status) {
298 InitFakeURLFetcherFactory(); 386 InitFakeURLFetcherFactory();
299 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data, 387 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data,
300 response_code, status); 388 response_code, status);
301 } 389 }
302 390
303 std::unique_ptr<translate::LanguageModel> MakeLanguageModel( 391 std::unique_ptr<translate::LanguageModel> MakeLanguageModel(
304 const std::vector<std::string>& codes) { 392 const std::vector<std::string>& codes) {
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); 993 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr));
906 EXPECT_THAT( 994 EXPECT_THAT(
907 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), 995 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"),
908 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); 996 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1)));
909 EXPECT_THAT(histogram_tester().GetAllSamples( 997 EXPECT_THAT(histogram_tester().GetAllSamples(
910 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), 998 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"),
911 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); 999 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1)));
912 } 1000 }
913 1001
914 TEST_F(NTPSnippetsFetcherTest, ShouldRestrictToHosts) { 1002 TEST_F(NTPSnippetsFetcherTest, ShouldRestrictToHosts) {
915 net::TestURLFetcherFactory test_url_fetcher_factory; 1003 DelegateCallingTestURLFetcherFactory fetcher_factory;
916 NTPSnippetsFetcher::Params params = test_params(); 1004 NTPSnippetsFetcher::Params params = test_params();
917 params.hosts = {"www.somehost1.com", "www.somehost2.com"}; 1005 params.hosts = {"www.somehost1.com", "www.somehost2.com"};
918 params.count_to_fetch = 17; 1006 params.count_to_fetch = 17;
1007
919 snippets_fetcher().FetchSnippets( 1008 snippets_fetcher().FetchSnippets(
920 params, ToSnippetsAvailableCallback(&mock_callback())); 1009 params, ToSnippetsAvailableCallback(&mock_callback()));
921 net::TestURLFetcher* fetcher = test_url_fetcher_factory.GetFetcherByID(0); 1010
1011 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher();
922 ASSERT_THAT(fetcher, NotNull()); 1012 ASSERT_THAT(fetcher, NotNull());
923 std::unique_ptr<base::Value> value = 1013 std::unique_ptr<base::Value> value =
924 base::JSONReader::Read(fetcher->upload_data()); 1014 base::JSONReader::Read(fetcher->upload_data());
925 ASSERT_TRUE(value) << " failed to parse JSON: " 1015 ASSERT_TRUE(value) << " failed to parse JSON: "
926 << PrintToString(fetcher->upload_data()); 1016 << PrintToString(fetcher->upload_data());
927 const base::DictionaryValue* dict = nullptr; 1017 const base::DictionaryValue* dict = nullptr;
928 ASSERT_TRUE(value->GetAsDictionary(&dict)); 1018 ASSERT_TRUE(value->GetAsDictionary(&dict));
929 const base::DictionaryValue* local_scoring_params = nullptr; 1019 const base::DictionaryValue* local_scoring_params = nullptr;
930 ASSERT_TRUE(dict->GetDictionary("advanced_options.local_scoring_params", 1020 ASSERT_TRUE(dict->GetDictionary("advanced_options.local_scoring_params",
931 &local_scoring_params)); 1021 &local_scoring_params));
932 const base::ListValue* content_selectors = nullptr; 1022 const base::ListValue* content_selectors = nullptr;
933 ASSERT_TRUE( 1023 ASSERT_TRUE(
934 local_scoring_params->GetList("content_selectors", &content_selectors)); 1024 local_scoring_params->GetList("content_selectors", &content_selectors));
935 ASSERT_THAT(content_selectors->GetSize(), Eq(static_cast<size_t>(2))); 1025 ASSERT_THAT(content_selectors->GetSize(), Eq(static_cast<size_t>(2)));
936 const base::DictionaryValue* content_selector = nullptr; 1026 const base::DictionaryValue* content_selector = nullptr;
937 ASSERT_TRUE(content_selectors->GetDictionary(0, &content_selector)); 1027 ASSERT_TRUE(content_selectors->GetDictionary(0, &content_selector));
938 std::string content_selector_value; 1028 std::string content_selector_value;
939 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value)); 1029 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value));
940 EXPECT_THAT(content_selector_value, Eq("www.somehost1.com")); 1030 EXPECT_THAT(content_selector_value, Eq("www.somehost1.com"));
941 ASSERT_TRUE(content_selectors->GetDictionary(1, &content_selector)); 1031 ASSERT_TRUE(content_selectors->GetDictionary(1, &content_selector));
942 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value)); 1032 EXPECT_TRUE(content_selector->GetString("value", &content_selector_value));
943 EXPECT_THAT(content_selector_value, Eq("www.somehost2.com")); 1033 EXPECT_THAT(content_selector_value, Eq("www.somehost2.com"));
944 // Call the delegate callback manually as the TestURLFetcher deletes any 1034 }
945 // call to the delegate that usually happens on |Start|. 1035
946 // Without the call to the delegate, it leaks the request that owns itself. 1036 TEST_F(NTPSnippetsFetcherTest, RetryOnInteractiveRequests) {
947 ASSERT_THAT(fetcher->delegate(), NotNull()); 1037 DelegateCallingTestURLFetcherFactory fetcher_factory;
948 EXPECT_CALL(mock_callback(), 1038 NTPSnippetsFetcher::Params params = test_params();
949 Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR, 1039 params.interactive_request = true;
950 /*snippets=*/Not(HasValue()))) 1040
951 .Times(1); 1041 snippets_fetcher().FetchSnippets(
952 // An 4XX response needs the least configuration to successfully invoke the 1042 params, ToSnippetsAvailableCallback(&mock_callback()));
953 // callback properly as the results are not important in this test. 1043
954 fetcher->set_response_code(net::HTTP_NOT_FOUND); 1044 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher();
955 fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, -2)); 1045 ASSERT_THAT(fetcher, NotNull());
956 fetcher->delegate()->OnURLFetchComplete(fetcher); 1046 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(2));
1047 }
1048
1049 TEST_F(NTPSnippetsFetcherTest, RetriesConfigurableOnNonInteractiveRequests) {
1050 struct ExpectationForVariationParam {
1051 std::string param_value;
1052 int expected_value;
1053 std::string description;
1054 };
1055 const std::vector<ExpectationForVariationParam> retry_config_expectation = {
1056 {"", 0, "Do not retry by default"},
1057 {"0", 0, "Do not retry on param value 0"},
1058 {"-1", 0, "Do not retry on negative param values."},
1059 {"4", 4, "Retry as set in param value."}};
1060
1061 NTPSnippetsFetcher::Params params = test_params();
1062 params.interactive_request = false;
1063
1064 for (const auto& retry_config : retry_config_expectation) {
1065 DelegateCallingTestURLFetcherFactory fetcher_factory;
1066 SetVariationParametersForFeatures(
1067 {{"background_5xx_retries_count", retry_config.param_value}},
1068 {ntp_snippets::kArticleSuggestionsFeature.name});
1069
1070 snippets_fetcher().FetchSnippets(
1071 params, ToSnippetsAvailableCallback(&mock_callback()));
1072
1073 net::TestURLFetcher* fetcher = fetcher_factory.GetLastCreatedFetcher();
1074 ASSERT_THAT(fetcher, NotNull());
1075 EXPECT_THAT(fetcher->GetMaxRetriesOn5xx(), Eq(retry_config.expected_value))
1076 << retry_config.description;
1077 }
957 } 1078 }
958 1079
959 TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) { 1080 TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) {
960 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND, 1081 SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
961 net::URLRequestStatus::FAILED); 1082 net::URLRequestStatus::FAILED);
962 EXPECT_CALL(mock_callback(), 1083 EXPECT_CALL(mock_callback(),
963 Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR, 1084 Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR,
964 /*snippets=*/Not(HasValue()))) 1085 /*snippets=*/Not(HasValue())))
965 .Times(1); 1086 .Times(1);
966 snippets_fetcher().FetchSnippets( 1087 snippets_fetcher().FetchSnippets(
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 const NTPSnippetsFetcher::OptionalFetchedCategories& fetched_categories) { 1237 const NTPSnippetsFetcher::OptionalFetchedCategories& fetched_categories) {
1117 if (fetched_categories) { 1238 if (fetched_categories) {
1118 // Matchers above aren't any more precise than this, so this is sufficient 1239 // Matchers above aren't any more precise than this, so this is sufficient
1119 // for test-failure diagnostics. 1240 // for test-failure diagnostics.
1120 return os << "list with " << fetched_categories->size() << " elements"; 1241 return os << "list with " << fetched_categories->size() << " elements";
1121 } 1242 }
1122 return os << "null"; 1243 return os << "null";
1123 } 1244 }
1124 1245
1125 } // namespace ntp_snippets 1246 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/remote/ntp_snippets_fetcher.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698