123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- // Copyright 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/ntp_snippets/remote/json_request.h"
- #include <set>
- #include <utility>
- #include "base/json/json_reader.h"
- #include "base/strings/stringprintf.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/test/test_mock_time_task_runner.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/time/tick_clock.h"
- #include "base/time/time.h"
- #include "base/values.h"
- #include "components/ntp_snippets/features.h"
- #include "components/ntp_snippets/ntp_snippets_constants.h"
- #include "components/ntp_snippets/remote/request_params.h"
- #include "components/prefs/testing_pref_service.h"
- #include "components/variations/scoped_variations_ids_provider.h"
- #include "services/network/public/cpp/shared_url_loader_factory.h"
- #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
- #include "services/network/test/test_url_loader_factory.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- // TODO(crbug.com/961023): Fix memory leaks in tests and re-enable on LSAN.
- #ifdef LEAK_SANITIZER
- #define MAYBE_BuildRequestAuthenticated DISABLED_BuildRequestAuthenticated
- #else
- #define MAYBE_BuildRequestAuthenticated BuildRequestAuthenticated
- #endif
- namespace ntp_snippets {
- namespace internal {
- namespace {
- using testing::_;
- using testing::Eq;
- using testing::Not;
- using testing::NotNull;
- using testing::StrEq;
- MATCHER_P(EqualsJSON, json, "equals JSON") {
- absl::optional<base::Value> expected = base::JSONReader::Read(json);
- if (!expected) {
- *result_listener << "INTERNAL ERROR: couldn't parse expected JSON";
- return false;
- }
- auto actual = base::JSONReader::ReadAndReturnValueWithError(arg);
- if (!actual.has_value()) {
- *result_listener << "input:" << actual.error().line << ":"
- << actual.error().column << ": "
- << "parse error: " << actual.error().message;
- return false;
- }
- return *expected == *actual;
- }
- } // namespace
- class JsonRequestTest : public testing::Test {
- public:
- JsonRequestTest()
- : pref_service_(std::make_unique<TestingPrefServiceSimple>()),
- mock_task_runner_(new base::TestMockTimeTaskRunner()),
- mock_runner_handle_(
- std::make_unique<base::ThreadTaskRunnerHandle>(mock_task_runner_)),
- test_shared_loader_factory_(
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- &test_url_loader_factory_)) {
- scoped_feature_list_.InitAndEnableFeatureWithParameters(
- kArticleSuggestionsFeature,
- {{"send_top_languages", "true"}, {"send_user_class", "true"}});
- language::UrlLanguageHistogram::RegisterProfilePrefs(
- pref_service_->registry());
- }
- JsonRequestTest(const JsonRequestTest&) = delete;
- JsonRequestTest& operator=(const JsonRequestTest&) = delete;
- std::unique_ptr<language::UrlLanguageHistogram> MakeLanguageHistogram(
- const std::set<std::string>& codes) {
- std::unique_ptr<language::UrlLanguageHistogram> language_histogram =
- std::make_unique<language::UrlLanguageHistogram>(pref_service_.get());
- // There must be at least 10 visits before the top languages are defined.
- for (int i = 0; i < 10; i++) {
- for (const std::string& code : codes) {
- language_histogram->OnPageVisited(code);
- }
- }
- return language_histogram;
- }
- JsonRequest::Builder CreateMinimalBuilder() {
- JsonRequest::Builder builder;
- builder.SetUrl(GURL("http://valid-url.test"))
- .SetClock(mock_task_runner_->GetMockClock())
- .SetUrlLoaderFactory(test_shared_loader_factory_);
- return builder;
- }
- std::unique_ptr<base::test::ScopedFeatureList> ForceOptionalImagesSupport(
- bool supported) {
- auto feature_list = std::make_unique<base::test::ScopedFeatureList>();
- if (supported) {
- feature_list->InitWithFeatures({kOptionalImagesEnabledFeature}, {});
- } else {
- feature_list->InitWithFeatures({}, {kOptionalImagesEnabledFeature});
- }
- return feature_list;
- }
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
- variations::ScopedVariationsIdsProvider scoped_variations_ids_provider_{
- variations::VariationsIdsProvider::Mode::kUseSignedInState};
- std::unique_ptr<TestingPrefServiceSimple> pref_service_;
- scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
- std::unique_ptr<base::ThreadTaskRunnerHandle> mock_runner_handle_;
- network::TestURLLoaderFactory test_url_loader_factory_;
- scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
- };
- TEST_F(JsonRequestTest, MAYBE_BuildRequestAuthenticated) {
- JsonRequest::Builder builder = CreateMinimalBuilder();
- RequestParams params;
- params.excluded_ids = {"1234567890"};
- params.count_to_fetch = 25;
- params.interactive_request = false;
- builder.SetParams(params)
- .SetUrl(GURL("http://valid-url.test"))
- .SetAuthentication("headerstuff")
- .SetUserClassForTesting("ACTIVE_NTP_USER")
- .Build();
- EXPECT_THAT(builder.PreviewRequestHeadersForTesting(),
- StrEq("Content-Type: application/json; charset=UTF-8\r\n"
- "Authorization: headerstuff\r\n"
- "\r\n"));
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"priority\": \"BACKGROUND_PREFETCH\","
- " \"excludedSuggestionIds\": ["
- " \"1234567890\""
- " ],"
- " \"userActivenessClass\": \"ACTIVE_NTP_USER\""
- "}"));
- }
- TEST_F(JsonRequestTest, BuildRequestUnauthenticated) {
- JsonRequest::Builder builder;
- RequestParams params;
- params.interactive_request = true;
- params.count_to_fetch = 10;
- builder.SetParams(params).SetUserClassForTesting("ACTIVE_NTP_USER");
- EXPECT_THAT(builder.PreviewRequestHeadersForTesting(),
- StrEq("Content-Type: application/json; charset=UTF-8\r\n"
- "\r\n"));
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"priority\": \"USER_ACTION\","
- " \"excludedSuggestionIds\": [],"
- " \"userActivenessClass\": \"ACTIVE_NTP_USER\""
- "}"));
- }
- TEST_F(JsonRequestTest, BuildRequestDisplayCapabilityDisabledByFeature) {
- auto optional_images_feature_list = ForceOptionalImagesSupport(false);
- JsonRequest::Builder builder;
- builder.SetOptionalImagesCapability(true);
- EXPECT_THAT(builder.PreviewRequestHeadersForTesting(),
- StrEq("Content-Type: application/json; charset=UTF-8\r\n"
- "\r\n"));
- // The JSON should not contain any mention of displayCapability.
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"excludedSuggestionIds\": [],"
- " \"priority\": \"BACKGROUND_PREFETCH\""
- "}"));
- }
- TEST_F(JsonRequestTest, BuildRequestDisplayCapabilityUnspecified) {
- auto optional_images_feature_list = ForceOptionalImagesSupport(true);
- JsonRequest::Builder builder;
- builder.SetOptionalImagesCapability(false);
- EXPECT_THAT(builder.PreviewRequestHeadersForTesting(),
- StrEq("Content-Type: application/json; charset=UTF-8\r\n"
- "\r\n"));
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"excludedSuggestionIds\": [],"
- " \"priority\": \"BACKGROUND_PREFETCH\""
- "}"));
- }
- TEST_F(JsonRequestTest, BuildRequestOptionalImages) {
- auto optional_images_feature_list = ForceOptionalImagesSupport(true);
- JsonRequest::Builder builder;
- builder.SetOptionalImagesCapability(true);
- EXPECT_THAT(builder.PreviewRequestHeadersForTesting(),
- StrEq("Content-Type: application/json; charset=UTF-8\r\n"
- "\r\n"));
- EXPECT_THAT(
- builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"displayCapability\": \"CAPABILITY_OPTIONAL_IMAGES\","
- " \"excludedSuggestionIds\": [],"
- " \"priority\": \"BACKGROUND_PREFETCH\""
- "}"));
- }
- TEST_F(JsonRequestTest, ShouldNotTruncateExcludedIdsList) {
- JsonRequest::Builder builder;
- RequestParams params;
- params.interactive_request = false;
- for (int i = 0; i < 200; ++i) {
- params.excluded_ids.insert(base::StringPrintf("%03d", i));
- }
- builder.SetParams(params).SetUserClassForTesting("ACTIVE_NTP_USER");
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"priority\": \"BACKGROUND_PREFETCH\","
- " \"excludedSuggestionIds\": ["
- " \"000\", \"001\", \"002\", \"003\", \"004\","
- " \"005\", \"006\", \"007\", \"008\", \"009\","
- " \"010\", \"011\", \"012\", \"013\", \"014\","
- " \"015\", \"016\", \"017\", \"018\", \"019\","
- " \"020\", \"021\", \"022\", \"023\", \"024\","
- " \"025\", \"026\", \"027\", \"028\", \"029\","
- " \"030\", \"031\", \"032\", \"033\", \"034\","
- " \"035\", \"036\", \"037\", \"038\", \"039\","
- " \"040\", \"041\", \"042\", \"043\", \"044\","
- " \"045\", \"046\", \"047\", \"048\", \"049\","
- " \"050\", \"051\", \"052\", \"053\", \"054\","
- " \"055\", \"056\", \"057\", \"058\", \"059\","
- " \"060\", \"061\", \"062\", \"063\", \"064\","
- " \"065\", \"066\", \"067\", \"068\", \"069\","
- " \"070\", \"071\", \"072\", \"073\", \"074\","
- " \"075\", \"076\", \"077\", \"078\", \"079\","
- " \"080\", \"081\", \"082\", \"083\", \"084\","
- " \"085\", \"086\", \"087\", \"088\", \"089\","
- " \"090\", \"091\", \"092\", \"093\", \"094\","
- " \"095\", \"096\", \"097\", \"098\", \"099\","
- " \"100\", \"101\", \"102\", \"103\", \"104\","
- " \"105\", \"106\", \"107\", \"108\", \"109\","
- " \"110\", \"111\", \"112\", \"113\", \"114\","
- " \"115\", \"116\", \"117\", \"118\", \"119\","
- " \"120\", \"121\", \"122\", \"123\", \"124\","
- " \"125\", \"126\", \"127\", \"128\", \"129\","
- " \"130\", \"131\", \"132\", \"133\", \"134\","
- " \"135\", \"136\", \"137\", \"138\", \"139\","
- " \"140\", \"141\", \"142\", \"143\", \"144\","
- " \"145\", \"146\", \"147\", \"148\", \"149\","
- " \"150\", \"151\", \"152\", \"153\", \"154\","
- " \"155\", \"156\", \"157\", \"158\", \"159\","
- " \"160\", \"161\", \"162\", \"163\", \"164\","
- " \"165\", \"166\", \"167\", \"168\", \"169\","
- " \"170\", \"171\", \"172\", \"173\", \"174\","
- " \"175\", \"176\", \"177\", \"178\", \"179\","
- " \"180\", \"181\", \"182\", \"183\", \"184\","
- " \"185\", \"186\", \"187\", \"188\", \"189\","
- " \"190\", \"191\", \"192\", \"193\", \"194\","
- " \"195\", \"196\", \"197\", \"198\", \"199\""
- " ],"
- " \"userActivenessClass\": \"ACTIVE_NTP_USER\""
- "}"));
- }
- TEST_F(JsonRequestTest, BuildRequestNoUserClass) {
- JsonRequest::Builder builder;
- RequestParams params;
- params.interactive_request = false;
- builder.SetParams(params);
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"priority\": \"BACKGROUND_PREFETCH\","
- " \"excludedSuggestionIds\": []"
- "}"));
- }
- TEST_F(JsonRequestTest, BuildRequestWithTwoLanguages) {
- JsonRequest::Builder builder;
- std::unique_ptr<language::UrlLanguageHistogram> language_histogram =
- MakeLanguageHistogram({"de", "en"});
- RequestParams params;
- params.interactive_request = true;
- params.language_code = "en";
- builder.SetParams(params).SetLanguageHistogram(language_histogram.get());
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"priority\": \"USER_ACTION\","
- " \"uiLanguage\": \"en\","
- " \"excludedSuggestionIds\": [],"
- " \"topLanguages\": ["
- " {"
- " \"language\" : \"en\","
- " \"frequency\" : 0.5"
- " },"
- " {"
- " \"language\" : \"de\","
- " \"frequency\" : 0.5"
- " }"
- " ]"
- "}"));
- }
- TEST_F(JsonRequestTest, BuildRequestWithUILanguageOnly) {
- JsonRequest::Builder builder;
- std::unique_ptr<language::UrlLanguageHistogram> language_histogram =
- MakeLanguageHistogram({"en"});
- RequestParams params;
- params.interactive_request = true;
- params.language_code = "en";
- builder.SetParams(params).SetLanguageHistogram(language_histogram.get());
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(),
- EqualsJSON("{"
- " \"priority\": \"USER_ACTION\","
- " \"uiLanguage\": \"en\","
- " \"excludedSuggestionIds\": [],"
- " \"topLanguages\": [{"
- " \"language\" : \"en\","
- " \"frequency\" : 1.0"
- " }]"
- "}"));
- }
- TEST_F(JsonRequestTest,
- ShouldPropagateCountToFetchWhenExclusiveCategoryPresent) {
- JsonRequest::Builder builder;
- RequestParams params;
- params.interactive_request = true;
- params.language_code = "en";
- params.exclusive_category =
- Category::FromKnownCategory(KnownCategories::ARTICLES);
- params.count_to_fetch = 25;
- builder.SetParams(params);
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(), EqualsJSON(R"(
- {
- "priority": "USER_ACTION",
- "uiLanguage": "en",
- "excludedSuggestionIds": [],
- "categoryParameters": [{
- "id": 1,
- "numSuggestions": 25
- }]
- }
- )"));
- }
- // TODO(vitaliii): Propagate count to fetch in this case as well and delete this
- // test. Currently the server does not support this.
- TEST_F(JsonRequestTest,
- ShouldNotPropagateCountToFetchWhenExclusiveCategoryNotPresent) {
- JsonRequest::Builder builder;
- RequestParams params;
- params.interactive_request = true;
- params.language_code = "en";
- params.count_to_fetch = 10;
- builder.SetParams(params);
- EXPECT_THAT(builder.PreviewRequestBodyForTesting(), EqualsJSON(R"(
- {
- "priority": "USER_ACTION",
- "uiLanguage": "en",
- "excludedSuggestionIds": []
- }
- )"));
- }
- } // namespace internal
- } // namespace ntp_snippets
|