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) { |
| 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 |