Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/ntp_snippets/remote/ntp_snippets_json_request.h" | |
| 6 | |
| 7 #include <set> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "base/json/json_reader.h" | |
| 11 #include "base/memory/ptr_util.h" | |
| 12 #include "base/strings/stringprintf.h" | |
| 13 #include "base/test/test_mock_time_task_runner.h" | |
| 14 #include "base/time/tick_clock.h" | |
| 15 #include "base/time/time.h" | |
| 16 #include "base/values.h" | |
| 17 #include "components/ntp_snippets/features.h" | |
| 18 #include "components/ntp_snippets/ntp_snippets_constants.h" | |
| 19 #include "components/ntp_snippets/remote/ntp_snippets_request_params.h" | |
| 20 #include "components/prefs/testing_pref_service.h" | |
| 21 #include "components/variations/variations_params_manager.h" | |
| 22 #include "net/url_request/test_url_fetcher_factory.h" | |
| 23 #include "net/url_request/url_request_test_util.h" | |
| 24 #include "testing/gmock/include/gmock/gmock.h" | |
| 25 #include "testing/gtest/include/gtest/gtest.h" | |
| 26 | |
| 27 namespace ntp_snippets { | |
| 28 | |
| 29 namespace internal { | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 using testing::_; | |
| 34 using testing::Eq; | |
| 35 using testing::Not; | |
| 36 using testing::NotNull; | |
| 37 using testing::StrEq; | |
| 38 | |
| 39 MATCHER_P(EqualsJSON, json, "equals JSON") { | |
| 40 std::unique_ptr<base::Value> expected = base::JSONReader::Read(json); | |
| 41 if (!expected) { | |
| 42 *result_listener << "INTERNAL ERROR: couldn't parse expected JSON"; | |
| 43 return false; | |
| 44 } | |
| 45 | |
| 46 std::string err_msg; | |
| 47 int err_line, err_col; | |
| 48 std::unique_ptr<base::Value> actual = base::JSONReader::ReadAndReturnError( | |
| 49 arg, base::JSON_PARSE_RFC, nullptr, &err_msg, &err_line, &err_col); | |
| 50 if (!actual) { | |
| 51 *result_listener << "input:" << err_line << ":" << err_col << ": " | |
| 52 << "parse error: " << err_msg; | |
| 53 return false; | |
| 54 } | |
| 55 return base::Value::Equals(actual.get(), expected.get()); | |
| 56 } | |
| 57 | |
| 58 } // namespace | |
| 59 | |
| 60 class NTPSnippetsJsonRequestTest : public testing::Test { | |
| 61 public: | |
| 62 NTPSnippetsJsonRequestTest() | |
| 63 : params_manager_( | |
| 64 ntp_snippets::kStudyName, | |
| 65 {{"send_top_languages", "true"}, {"send_user_class", "true"}}, | |
| 66 {ntp_snippets::kArticleSuggestionsFeature.name}), | |
| 67 pref_service_(base::MakeUnique<TestingPrefServiceSimple>()), | |
| 68 mock_task_runner_(new base::TestMockTimeTaskRunner()), | |
| 69 tick_clock_(mock_task_runner_->GetMockTickClock()), | |
| 70 request_context_getter_( | |
| 71 new net::TestURLRequestContextGetter(mock_task_runner_.get())) { | |
| 72 translate::LanguageModel::RegisterProfilePrefs(pref_service_->registry()); | |
| 73 } | |
| 74 | |
| 75 std::unique_ptr<translate::LanguageModel> MakeLanguageModel( | |
| 76 const std::set<std::string>& codes) { | |
| 77 std::unique_ptr<translate::LanguageModel> language_model = | |
| 78 base::MakeUnique<translate::LanguageModel>(pref_service_.get()); | |
| 79 // There must be at least 10 visits before the top languages are defined. | |
| 80 for (int i = 0; i < 10; i++) { | |
| 81 for (const auto& code : codes) { | |
|
Bernhard Bauer
2016/12/20 10:49:35
Use the real type instead of auto?
fhorschig
2016/12/20 12:11:37
Done.
| |
| 82 language_model->OnPageVisited(code); | |
| 83 } | |
| 84 } | |
| 85 return language_model; | |
| 86 } | |
| 87 | |
| 88 NTPSnippetsJsonRequest::Builder CreateMinimalBuilder() { | |
| 89 NTPSnippetsJsonRequest::Builder builder; | |
| 90 builder.SetUrl(GURL("http://valid-url.test")) | |
| 91 .SetTickClock(tick_clock_.get()) | |
| 92 .SetUrlRequestContextGetter(request_context_getter_.get()); | |
| 93 return builder; | |
| 94 } | |
| 95 | |
| 96 private: | |
| 97 variations::testing::VariationParamsManager params_manager_; | |
| 98 std::unique_ptr<TestingPrefServiceSimple> pref_service_; | |
| 99 scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_; | |
| 100 std::unique_ptr<base::TickClock> tick_clock_; | |
| 101 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; | |
| 102 net::TestURLFetcherFactory fetcher_factory_; | |
| 103 | |
| 104 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsJsonRequestTest); | |
| 105 }; | |
| 106 | |
| 107 TEST_F(NTPSnippetsJsonRequestTest, BuildRequestAuthenticated) { | |
| 108 NTPSnippetsJsonRequest::Builder builder = CreateMinimalBuilder(); | |
| 109 NTPSnippetsRequestParams params; | |
| 110 params.excluded_ids = {"1234567890"}; | |
| 111 params.count_to_fetch = 25; | |
| 112 params.interactive_request = false; | |
| 113 builder.SetParams(params) | |
| 114 .SetUrl(GURL("http://valid-url.test")) | |
| 115 .SetUrl(GURL("http://valid-url.test")) | |
| 116 .SetAuthentication("0BFUSGAIA", "headerstuff") | |
| 117 .SetPersonalization(Personalization::kPersonal) | |
| 118 .SetUserClassForTesting("ACTIVE_NTP_USER") | |
| 119 .SetFetchAPI(FetchAPI::CHROME_READER_API) | |
| 120 .Build(); | |
| 121 | |
| 122 EXPECT_THAT(builder.PreviewRequestHeadersForTesting(), | |
| 123 StrEq("Content-Type: application/json; charset=UTF-8\r\n" | |
| 124 "Authorization: headerstuff\r\n" | |
| 125 "\r\n")); | |
| 126 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 127 EqualsJSON("{" | |
| 128 " \"response_detail_level\": \"STANDARD\"," | |
| 129 " \"obfuscated_gaia_id\": \"0BFUSGAIA\"," | |
| 130 " \"advanced_options\": {" | |
| 131 " \"local_scoring_params\": {" | |
| 132 " \"content_params\": {" | |
| 133 " \"only_return_personalized_results\": true" | |
| 134 " }," | |
| 135 " \"content_restricts\": [" | |
| 136 " {" | |
| 137 " \"type\": \"METADATA\"," | |
| 138 " \"value\": \"TITLE\"" | |
| 139 " }," | |
| 140 " {" | |
| 141 " \"type\": \"METADATA\"," | |
| 142 " \"value\": \"SNIPPET\"" | |
| 143 " }," | |
| 144 " {" | |
| 145 " \"type\": \"METADATA\"," | |
| 146 " \"value\": \"THUMBNAIL\"" | |
| 147 " }" | |
| 148 " ]" | |
| 149 " }," | |
| 150 " \"global_scoring_params\": {" | |
| 151 " \"num_to_return\": 25," | |
| 152 " \"sort_type\": 1" | |
| 153 " }" | |
| 154 " }" | |
| 155 "}")); | |
| 156 | |
| 157 builder.SetFetchAPI(FetchAPI::CHROME_CONTENT_SUGGESTIONS_API); | |
| 158 | |
| 159 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 160 EqualsJSON("{" | |
| 161 " \"priority\": \"BACKGROUND_PREFETCH\"," | |
| 162 " \"excludedSuggestionIds\": [" | |
| 163 " \"1234567890\"" | |
| 164 " ]," | |
| 165 " \"userActivenessClass\": \"ACTIVE_NTP_USER\"" | |
| 166 "}")); | |
| 167 } | |
| 168 | |
| 169 TEST_F(NTPSnippetsJsonRequestTest, BuildRequestUnauthenticated) { | |
| 170 NTPSnippetsJsonRequest::Builder builder; | |
| 171 NTPSnippetsRequestParams params; | |
| 172 params.interactive_request = true; | |
| 173 params.count_to_fetch = 10; | |
| 174 builder.SetParams(params) | |
| 175 .SetUserClassForTesting("ACTIVE_NTP_USER") | |
| 176 .SetPersonalization(Personalization::kNonPersonal) | |
| 177 .SetFetchAPI(FetchAPI::CHROME_READER_API); | |
| 178 | |
| 179 EXPECT_THAT(builder.PreviewRequestHeadersForTesting(), | |
| 180 StrEq("Content-Type: application/json; charset=UTF-8\r\n" | |
| 181 "\r\n")); | |
| 182 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 183 EqualsJSON("{" | |
| 184 " \"response_detail_level\": \"STANDARD\"," | |
| 185 " \"advanced_options\": {" | |
| 186 " \"local_scoring_params\": {" | |
| 187 " \"content_params\": {" | |
| 188 " \"only_return_personalized_results\": false" | |
| 189 " }," | |
| 190 " \"content_restricts\": [" | |
| 191 " {" | |
| 192 " \"type\": \"METADATA\"," | |
| 193 " \"value\": \"TITLE\"" | |
| 194 " }," | |
| 195 " {" | |
| 196 " \"type\": \"METADATA\"," | |
| 197 " \"value\": \"SNIPPET\"" | |
| 198 " }," | |
| 199 " {" | |
| 200 " \"type\": \"METADATA\"," | |
| 201 " \"value\": \"THUMBNAIL\"" | |
| 202 " }" | |
| 203 " ]" | |
| 204 " }," | |
| 205 " \"global_scoring_params\": {" | |
| 206 " \"num_to_return\": 10," | |
| 207 " \"sort_type\": 1" | |
| 208 " }" | |
| 209 " }" | |
| 210 "}")); | |
| 211 | |
| 212 builder.SetFetchAPI(FetchAPI::CHROME_CONTENT_SUGGESTIONS_API); | |
| 213 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 214 EqualsJSON("{" | |
| 215 " \"priority\": \"USER_ACTION\"," | |
| 216 " \"excludedSuggestionIds\": []," | |
| 217 " \"userActivenessClass\": \"ACTIVE_NTP_USER\"" | |
| 218 "}")); | |
| 219 } | |
| 220 | |
| 221 TEST_F(NTPSnippetsJsonRequestTest, BuildRequestExcludedIds) { | |
| 222 NTPSnippetsJsonRequest::Builder builder; | |
| 223 NTPSnippetsRequestParams params; | |
| 224 params.interactive_request = false; | |
| 225 for (int i = 0; i < 200; ++i) { | |
| 226 params.excluded_ids.insert(base::StringPrintf("%03d", i)); | |
| 227 } | |
| 228 builder.SetParams(params) | |
| 229 .SetUserClassForTesting("ACTIVE_NTP_USER") | |
| 230 .SetPersonalization(Personalization::kNonPersonal) | |
| 231 .SetFetchAPI(FetchAPI::CHROME_CONTENT_SUGGESTIONS_API); | |
| 232 | |
| 233 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 234 EqualsJSON("{" | |
| 235 " \"priority\": \"BACKGROUND_PREFETCH\"," | |
| 236 " \"excludedSuggestionIds\": [" | |
| 237 " \"000\", \"001\", \"002\", \"003\", \"004\"," | |
| 238 " \"005\", \"006\", \"007\", \"008\", \"009\"," | |
| 239 " \"010\", \"011\", \"012\", \"013\", \"014\"," | |
| 240 " \"015\", \"016\", \"017\", \"018\", \"019\"," | |
| 241 " \"020\", \"021\", \"022\", \"023\", \"024\"," | |
| 242 " \"025\", \"026\", \"027\", \"028\", \"029\"," | |
| 243 " \"030\", \"031\", \"032\", \"033\", \"034\"," | |
| 244 " \"035\", \"036\", \"037\", \"038\", \"039\"," | |
| 245 " \"040\", \"041\", \"042\", \"043\", \"044\"," | |
| 246 " \"045\", \"046\", \"047\", \"048\", \"049\"," | |
| 247 " \"050\", \"051\", \"052\", \"053\", \"054\"," | |
| 248 " \"055\", \"056\", \"057\", \"058\", \"059\"," | |
| 249 " \"060\", \"061\", \"062\", \"063\", \"064\"," | |
| 250 " \"065\", \"066\", \"067\", \"068\", \"069\"," | |
| 251 " \"070\", \"071\", \"072\", \"073\", \"074\"," | |
| 252 " \"075\", \"076\", \"077\", \"078\", \"079\"," | |
| 253 " \"080\", \"081\", \"082\", \"083\", \"084\"," | |
| 254 " \"085\", \"086\", \"087\", \"088\", \"089\"," | |
| 255 " \"090\", \"091\", \"092\", \"093\", \"094\"," | |
| 256 " \"095\", \"096\", \"097\", \"098\", \"099\"" | |
| 257 // Truncated to 100 entries. Currently, they happen to | |
| 258 // be those lexically first. | |
| 259 " ]," | |
| 260 " \"userActivenessClass\": \"ACTIVE_NTP_USER\"" | |
| 261 "}")); | |
| 262 } | |
| 263 | |
| 264 TEST_F(NTPSnippetsJsonRequestTest, BuildRequestNoUserClass) { | |
| 265 NTPSnippetsJsonRequest::Builder builder; | |
| 266 NTPSnippetsRequestParams params; | |
| 267 params.interactive_request = false; | |
| 268 builder.SetPersonalization(Personalization::kNonPersonal) | |
| 269 .SetParams(params) | |
| 270 .SetFetchAPI(FetchAPI::CHROME_CONTENT_SUGGESTIONS_API); | |
| 271 | |
| 272 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 273 EqualsJSON("{" | |
| 274 " \"priority\": \"BACKGROUND_PREFETCH\"," | |
| 275 " \"excludedSuggestionIds\": []" | |
| 276 "}")); | |
| 277 } | |
| 278 | |
| 279 TEST_F(NTPSnippetsJsonRequestTest, BuildRequestWithTwoLanguages) { | |
| 280 NTPSnippetsJsonRequest::Builder builder; | |
| 281 std::unique_ptr<translate::LanguageModel> language_model = | |
| 282 MakeLanguageModel({"de", "en"}); | |
| 283 NTPSnippetsRequestParams params; | |
| 284 params.interactive_request = true; | |
| 285 params.language_code = "en"; | |
| 286 builder.SetParams(params) | |
| 287 .SetLanguageModel(language_model.get()) | |
| 288 .SetPersonalization(Personalization::kNonPersonal) | |
| 289 .SetFetchAPI(FetchAPI::CHROME_CONTENT_SUGGESTIONS_API); | |
| 290 | |
| 291 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 292 EqualsJSON("{" | |
| 293 " \"priority\": \"USER_ACTION\"," | |
| 294 " \"uiLanguage\": \"en\"," | |
| 295 " \"excludedSuggestionIds\": []," | |
| 296 " \"topLanguages\": [" | |
| 297 " {" | |
| 298 " \"language\" : \"en\"," | |
| 299 " \"frequency\" : 0.5" | |
| 300 " }," | |
| 301 " {" | |
| 302 " \"language\" : \"de\"," | |
| 303 " \"frequency\" : 0.5" | |
| 304 " }" | |
| 305 " ]" | |
| 306 "}")); | |
| 307 } | |
| 308 | |
| 309 TEST_F(NTPSnippetsJsonRequestTest, BuildRequestWithUILanguageOnly) { | |
| 310 NTPSnippetsJsonRequest::Builder builder; | |
| 311 std::unique_ptr<translate::LanguageModel> language_model = | |
| 312 MakeLanguageModel({"en"}); | |
| 313 NTPSnippetsRequestParams params; | |
| 314 params.interactive_request = true; | |
| 315 params.language_code = "en"; | |
| 316 builder.SetParams(params) | |
| 317 .SetLanguageModel(language_model.get()) | |
| 318 .SetPersonalization(Personalization::kNonPersonal) | |
| 319 .SetFetchAPI(FetchAPI::CHROME_CONTENT_SUGGESTIONS_API); | |
| 320 | |
| 321 EXPECT_THAT(builder.PreviewRequestBodyForTesting(), | |
| 322 EqualsJSON("{" | |
| 323 " \"priority\": \"USER_ACTION\"," | |
| 324 " \"uiLanguage\": \"en\"," | |
| 325 " \"excludedSuggestionIds\": []," | |
| 326 " \"topLanguages\": [{" | |
| 327 " \"language\" : \"en\"," | |
| 328 " \"frequency\" : 1.0" | |
| 329 " }]" | |
| 330 "}")); | |
| 331 } | |
| 332 | |
| 333 } // namespace internal | |
| 334 | |
| 335 } // namespace ntp_snippets | |
| OLD | NEW |