| OLD | NEW |
| 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/ntp_snippets_fetcher.h" | 5 #include "components/ntp_snippets/ntp_snippets_fetcher.h" |
| 6 | 6 |
| 7 #include "base/json/json_reader.h" | 7 #include "base/json/json_reader.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/message_loop/message_loop.h" | |
| 10 #include "base/run_loop.h" | |
| 11 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 12 #include "base/test/histogram_tester.h" | 10 #include "base/test/histogram_tester.h" |
| 11 #include "base/test/test_mock_time_task_runner.h" |
| 13 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
| 13 #include "base/time/time.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "components/ntp_snippets/ntp_snippet.h" | 15 #include "components/ntp_snippets/ntp_snippet.h" |
| 16 #include "google_apis/google_api_keys.h" | 16 #include "google_apis/google_api_keys.h" |
| 17 #include "net/url_request/test_url_fetcher_factory.h" | 17 #include "net/url_request/test_url_fetcher_factory.h" |
| 18 #include "net/url_request/url_request_test_util.h" | 18 #include "net/url_request/url_request_test_util.h" |
| 19 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 21 |
| 22 namespace ntp_snippets { | 22 namespace ntp_snippets { |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 using testing::ElementsAre; | 25 using testing::ElementsAre; |
| 26 using testing::Eq; | 26 using testing::Eq; |
| 27 using testing::IsEmpty; | 27 using testing::IsEmpty; |
| 28 using testing::IsNull; | 28 using testing::IsNull; |
| 29 using testing::Not; | 29 using testing::Not; |
| 30 using testing::NotNull; | 30 using testing::NotNull; |
| 31 using testing::PrintToString; | 31 using testing::PrintToString; |
| 32 using testing::SizeIs; | 32 using testing::SizeIs; |
| 33 using testing::StartsWith; | 33 using testing::StartsWith; |
| 34 | 34 |
| 35 const char kTestContentSnippetsServerFormat[] = | 35 const char kTestContentSnippetsServerFormat[] = |
| 36 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s"; | 36 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s"; |
| 37 // Artificial time delay for JSON parsing. |
| 38 const int64_t kTestJsonParsingLatencyMs = 20; |
| 37 | 39 |
| 38 MATCHER(HasValue, "") { | 40 MATCHER(HasValue, "") { |
| 39 return static_cast<bool>(arg); | 41 return static_cast<bool>(arg); |
| 40 } | 42 } |
| 41 | 43 |
| 42 MATCHER_P(PointeeSizeIs, | 44 MATCHER_P(PointeeSizeIs, |
| 43 size, | 45 size, |
| 44 std::string("contains a value with size ") + PrintToString(size)) { | 46 std::string("contains a value with size ") + PrintToString(size)) { |
| 45 return arg && static_cast<int>(arg->size()) == size; | 47 return arg && static_cast<int>(arg->size()) == size; |
| 46 } | 48 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 72 const ntp_snippets::NTPSnippetsFetcher::SuccessCallback& success_callback, | 74 const ntp_snippets::NTPSnippetsFetcher::SuccessCallback& success_callback, |
| 73 const ntp_snippets::NTPSnippetsFetcher::ErrorCallback& error_callback) { | 75 const ntp_snippets::NTPSnippetsFetcher::ErrorCallback& error_callback) { |
| 74 base::JSONReader json_reader; | 76 base::JSONReader json_reader; |
| 75 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); | 77 std::unique_ptr<base::Value> value = json_reader.ReadToValue(json); |
| 76 if (value) | 78 if (value) |
| 77 success_callback.Run(std::move(value)); | 79 success_callback.Run(std::move(value)); |
| 78 else | 80 else |
| 79 error_callback.Run(json_reader.GetErrorMessage()); | 81 error_callback.Run(json_reader.GetErrorMessage()); |
| 80 } | 82 } |
| 81 | 83 |
| 84 void ParseJsonDelayed( |
| 85 const std::string& json, |
| 86 const ntp_snippets::NTPSnippetsFetcher::SuccessCallback& success_callback, |
| 87 const ntp_snippets::NTPSnippetsFetcher::ErrorCallback& error_callback) { |
| 88 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 89 FROM_HERE, base::Bind(&ParseJson, json, success_callback, error_callback), |
| 90 base::TimeDelta::FromMilliseconds(kTestJsonParsingLatencyMs)); |
| 91 } |
| 92 |
| 82 class NTPSnippetsFetcherTest : public testing::Test { | 93 class NTPSnippetsFetcherTest : public testing::Test { |
| 83 public: | 94 public: |
| 84 NTPSnippetsFetcherTest() | 95 NTPSnippetsFetcherTest() |
| 85 : snippets_fetcher_(scoped_refptr<net::TestURLRequestContextGetter>( | 96 : mock_task_runner_(new base::TestMockTimeTaskRunner()), |
| 86 new net::TestURLRequestContextGetter( | 97 mock_task_runner_handle_(mock_task_runner_), |
| 87 base::ThreadTaskRunnerHandle::Get())), | 98 snippets_fetcher_( |
| 88 base::Bind(&ParseJson), | 99 scoped_refptr<net::TestURLRequestContextGetter>( |
| 89 /*is_stable_channel=*/true), | 100 new net::TestURLRequestContextGetter(mock_task_runner_.get())), |
| 101 base::Bind(&ParseJsonDelayed), |
| 102 /*is_stable_channel=*/true), |
| 90 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, | 103 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, |
| 91 google_apis::GetAPIKey().c_str())) { | 104 google_apis::GetAPIKey().c_str())) { |
| 92 snippets_fetcher_.SetCallback( | 105 snippets_fetcher_.SetCallback( |
| 93 base::Bind(&MockSnippetsAvailableCallback::WrappedRun, | 106 base::Bind(&MockSnippetsAvailableCallback::WrappedRun, |
| 94 base::Unretained(&mock_callback_))); | 107 base::Unretained(&mock_callback_))); |
| 108 snippets_fetcher_.SetTickClockForTesting( |
| 109 mock_task_runner_->GetMockTickClock()); |
| 95 test_hosts_.insert("www.somehost.com"); | 110 test_hosts_.insert("www.somehost.com"); |
| 111 // Increase initial time such that ticks are non-zero. |
| 112 mock_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1234)); |
| 96 } | 113 } |
| 97 | 114 |
| 98 NTPSnippetsFetcher& snippets_fetcher() { return snippets_fetcher_; } | 115 NTPSnippetsFetcher& snippets_fetcher() { return snippets_fetcher_; } |
| 99 MockSnippetsAvailableCallback& mock_callback() { return mock_callback_; } | 116 MockSnippetsAvailableCallback& mock_callback() { return mock_callback_; } |
| 100 void RunUntilIdle() { message_loop_.RunUntilIdle(); } | 117 void FastForwardUntilNoTasksRemain() { |
| 118 mock_task_runner_->FastForwardUntilNoTasksRemain(); |
| 119 } |
| 101 const GURL& test_url() { return test_url_; } | 120 const GURL& test_url() { return test_url_; } |
| 102 const std::set<std::string>& test_hosts() const { return test_hosts_; } | 121 const std::set<std::string>& test_hosts() const { return test_hosts_; } |
| 103 base::HistogramTester& histogram_tester() { return histogram_tester_; } | 122 base::HistogramTester& histogram_tester() { return histogram_tester_; } |
| 104 | 123 |
| 105 void InitFakeURLFetcherFactory() { | 124 void InitFakeURLFetcherFactory() { |
| 106 if (fake_url_fetcher_factory_) | 125 if (fake_url_fetcher_factory_) |
| 107 return; | 126 return; |
| 108 // Instantiation of factory automatically sets itself as URLFetcher's | 127 // Instantiation of factory automatically sets itself as URLFetcher's |
| 109 // factory. | 128 // factory. |
| 110 fake_url_fetcher_factory_.reset(new net::FakeURLFetcherFactory( | 129 fake_url_fetcher_factory_.reset(new net::FakeURLFetcherFactory( |
| 111 /*default_factory=*/&failing_url_fetcher_factory_)); | 130 /*default_factory=*/&failing_url_fetcher_factory_)); |
| 112 } | 131 } |
| 113 | 132 |
| 114 void SetFakeResponse(const std::string& response_data, | 133 void SetFakeResponse(const std::string& response_data, |
| 115 net::HttpStatusCode response_code, | 134 net::HttpStatusCode response_code, |
| 116 net::URLRequestStatus::Status status) { | 135 net::URLRequestStatus::Status status) { |
| 117 InitFakeURLFetcherFactory(); | 136 InitFakeURLFetcherFactory(); |
| 118 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data, | 137 fake_url_fetcher_factory_->SetFakeResponse(test_url_, response_data, |
| 119 response_code, status); | 138 response_code, status); |
| 120 } | 139 } |
| 121 | 140 |
| 122 private: | 141 private: |
| 142 scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_; |
| 143 base::ThreadTaskRunnerHandle mock_task_runner_handle_; |
| 123 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; | 144 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; |
| 124 // Initialized lazily in SetFakeResponse(). | 145 // Initialized lazily in SetFakeResponse(). |
| 125 std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_; | 146 std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_; |
| 126 // Needed to use ThreadTaskRunnerHandle. | |
| 127 base::MessageLoop message_loop_; | |
| 128 NTPSnippetsFetcher snippets_fetcher_; | 147 NTPSnippetsFetcher snippets_fetcher_; |
| 129 MockSnippetsAvailableCallback mock_callback_; | 148 MockSnippetsAvailableCallback mock_callback_; |
| 130 const GURL test_url_; | 149 const GURL test_url_; |
| 131 std::set<std::string> test_hosts_; | 150 std::set<std::string> test_hosts_; |
| 132 base::HistogramTester histogram_tester_; | 151 base::HistogramTester histogram_tester_; |
| 133 | 152 |
| 134 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsFetcherTest); | 153 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsFetcherTest); |
| 135 }; | 154 }; |
| 136 | 155 |
| 137 TEST_F(NTPSnippetsFetcherTest, ShouldNotFetchOnCreation) { | 156 TEST_F(NTPSnippetsFetcherTest, ShouldNotFetchOnCreation) { |
| 138 // The lack of registered baked in responses would cause any fetch to fail. | 157 // The lack of registered baked in responses would cause any fetch to fail. |
| 139 RunUntilIdle(); | 158 FastForwardUntilNoTasksRemain(); |
| 140 EXPECT_THAT(histogram_tester().GetAllSamples( | 159 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 141 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 160 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 142 IsEmpty()); | 161 IsEmpty()); |
| 162 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 163 IsEmpty()); |
| 143 EXPECT_THAT(snippets_fetcher().last_status(), IsEmpty()); | 164 EXPECT_THAT(snippets_fetcher().last_status(), IsEmpty()); |
| 144 } | 165 } |
| 145 | 166 |
| 146 TEST_F(NTPSnippetsFetcherTest, ShouldFetchSuccessfully) { | 167 TEST_F(NTPSnippetsFetcherTest, ShouldFetchSuccessfully) { |
| 147 const std::string kJsonStr = | 168 const std::string kJsonStr = |
| 148 "{\"recos\": [{" | 169 "{\"recos\": [{" |
| 149 " \"contentInfo\": {" | 170 " \"contentInfo\": {" |
| 150 " \"url\" : \"http://localhost/foobar\"," | 171 " \"url\" : \"http://localhost/foobar\"," |
| 151 " \"sourceCorpusInfo\" : [{" | 172 " \"sourceCorpusInfo\" : [{" |
| 152 " \"ampUrl\" : \"http://localhost/amp\"," | 173 " \"ampUrl\" : \"http://localhost/amp\"," |
| 153 " \"corpusId\" : \"http://localhost/foobar\"," | 174 " \"corpusId\" : \"http://localhost/foobar\"," |
| 154 " \"publisherData\": { \"sourceName\" : \"Foo News\" }" | 175 " \"publisherData\": { \"sourceName\" : \"Foo News\" }" |
| 155 " }]" | 176 " }]" |
| 156 " }" | 177 " }" |
| 157 "}]}"; | 178 "}]}"; |
| 158 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, | 179 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, |
| 159 net::URLRequestStatus::SUCCESS); | 180 net::URLRequestStatus::SUCCESS); |
| 160 EXPECT_CALL(mock_callback(), Run(/*snippets=*/PointeeSizeIs(1))).Times(1); | 181 EXPECT_CALL(mock_callback(), Run(/*snippets=*/PointeeSizeIs(1))).Times(1); |
| 161 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 182 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 162 RunUntilIdle(); | 183 FastForwardUntilNoTasksRemain(); |
| 163 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); | 184 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); |
| 164 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 185 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); |
| 165 EXPECT_THAT(histogram_tester().GetAllSamples( | 186 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 166 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 187 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 167 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 188 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 189 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 190 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 191 /*count=*/1))); |
| 168 } | 192 } |
| 169 | 193 |
| 170 TEST_F(NTPSnippetsFetcherTest, ShouldFetchSuccessfullyEmptyList) { | 194 TEST_F(NTPSnippetsFetcherTest, ShouldFetchSuccessfullyEmptyList) { |
| 171 const std::string kJsonStr = "{\"recos\": []}"; | 195 const std::string kJsonStr = "{\"recos\": []}"; |
| 172 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, | 196 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, |
| 173 net::URLRequestStatus::SUCCESS); | 197 net::URLRequestStatus::SUCCESS); |
| 174 EXPECT_CALL(mock_callback(), Run(/*snippets=*/PointeeSizeIs(0))).Times(1); | 198 EXPECT_CALL(mock_callback(), Run(/*snippets=*/PointeeSizeIs(0))).Times(1); |
| 175 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 199 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 176 RunUntilIdle(); | 200 FastForwardUntilNoTasksRemain(); |
| 177 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); | 201 EXPECT_THAT(snippets_fetcher().last_status(), Eq("OK")); |
| 178 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 202 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); |
| 179 EXPECT_THAT( | 203 EXPECT_THAT( |
| 180 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 204 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 181 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); | 205 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); |
| 182 EXPECT_THAT(histogram_tester().GetAllSamples( | 206 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 183 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 207 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 184 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 208 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 185 } | 209 } |
| 186 | 210 |
| 187 TEST_F(NTPSnippetsFetcherTest, ShouldReportEmptyHostsError) { | 211 TEST_F(NTPSnippetsFetcherTest, ShouldReportEmptyHostsError) { |
| 188 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); | 212 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); |
| 189 snippets_fetcher().FetchSnippetsFromHosts(/*hosts=*/std::set<std::string>(), | 213 snippets_fetcher().FetchSnippetsFromHosts(/*hosts=*/std::set<std::string>(), |
| 190 /*count=*/1); | 214 /*count=*/1); |
| 191 RunUntilIdle(); | 215 FastForwardUntilNoTasksRemain(); |
| 192 EXPECT_THAT(snippets_fetcher().last_status(), | 216 EXPECT_THAT(snippets_fetcher().last_status(), |
| 193 Eq("Cannot fetch for empty hosts list.")); | 217 Eq("Cannot fetch for empty hosts list.")); |
| 194 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); | 218 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); |
| 195 EXPECT_THAT( | 219 EXPECT_THAT( |
| 196 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 220 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 197 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); | 221 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); |
| 198 EXPECT_THAT(histogram_tester().GetAllSamples( | 222 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 199 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 223 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 200 IsEmpty()); | 224 IsEmpty()); |
| 225 // This particular error gets triggered prior to JSON parsing and hence tests |
| 226 // observe no fetch latency. |
| 227 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 228 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); |
| 201 } | 229 } |
| 202 | 230 |
| 203 TEST_F(NTPSnippetsFetcherTest, ShouldRestrictToHosts) { | 231 TEST_F(NTPSnippetsFetcherTest, ShouldRestrictToHosts) { |
| 204 net::TestURLFetcherFactory test_url_fetcher_factory; | 232 net::TestURLFetcherFactory test_url_fetcher_factory; |
| 205 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/17); | 233 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/17); |
| 206 net::TestURLFetcher* fetcher = test_url_fetcher_factory.GetFetcherByID(0); | 234 net::TestURLFetcher* fetcher = test_url_fetcher_factory.GetFetcherByID(0); |
| 207 ASSERT_THAT(fetcher, NotNull()); | 235 ASSERT_THAT(fetcher, NotNull()); |
| 208 std::unique_ptr<base::Value> value = | 236 std::unique_ptr<base::Value> value = |
| 209 base::JSONReader::Read(fetcher->upload_data()); | 237 base::JSONReader::Read(fetcher->upload_data()); |
| 210 ASSERT_TRUE(value); | 238 ASSERT_TRUE(value); |
| 211 const base::DictionaryValue* dict; | 239 const base::DictionaryValue* dict; |
| 212 ASSERT_TRUE(value->GetAsDictionary(&dict)); | 240 ASSERT_TRUE(value->GetAsDictionary(&dict)); |
| 213 const base::DictionaryValue* local_scoring_params; | 241 const base::DictionaryValue* local_scoring_params; |
| 214 ASSERT_TRUE(dict->GetDictionary("advanced_options.local_scoring_params", | 242 ASSERT_TRUE(dict->GetDictionary("advanced_options.local_scoring_params", |
| 215 &local_scoring_params)); | 243 &local_scoring_params)); |
| 216 const base::DictionaryValue* content_selectors; | 244 const base::DictionaryValue* content_selectors; |
| 217 ASSERT_TRUE(local_scoring_params->GetDictionary("content_selectors", | 245 ASSERT_TRUE(local_scoring_params->GetDictionary("content_selectors", |
| 218 &content_selectors)); | 246 &content_selectors)); |
| 219 std::string content_selector_value; | 247 std::string content_selector_value; |
| 220 EXPECT_TRUE(content_selectors->GetString("value", &content_selector_value)); | 248 EXPECT_TRUE(content_selectors->GetString("value", &content_selector_value)); |
| 221 EXPECT_THAT(content_selector_value, Eq("www.somehost.com")); | 249 EXPECT_THAT(content_selector_value, Eq("www.somehost.com")); |
| 222 } | 250 } |
| 223 | 251 |
| 224 TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) { | 252 TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) { |
| 225 SetFakeResponse(/*data=*/std::string(), net::HTTP_NOT_FOUND, | 253 SetFakeResponse(/*data=*/std::string(), net::HTTP_NOT_FOUND, |
| 226 net::URLRequestStatus::FAILED); | 254 net::URLRequestStatus::FAILED); |
| 227 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); | 255 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); |
| 228 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 256 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 229 RunUntilIdle(); | 257 FastForwardUntilNoTasksRemain(); |
| 230 EXPECT_THAT(snippets_fetcher().last_status(), | 258 EXPECT_THAT(snippets_fetcher().last_status(), |
| 231 Eq("URLRequestStatus error -2")); | 259 Eq("URLRequestStatus error -2")); |
| 232 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); | 260 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); |
| 233 EXPECT_THAT( | 261 EXPECT_THAT( |
| 234 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 262 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 235 ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); | 263 ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); |
| 236 EXPECT_THAT(histogram_tester().GetAllSamples( | 264 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 237 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 265 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 238 ElementsAre(base::Bucket(/*min=*/-2, /*count=*/1))); | 266 ElementsAre(base::Bucket(/*min=*/-2, /*count=*/1))); |
| 267 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 268 Not(IsEmpty())); |
| 239 } | 269 } |
| 240 | 270 |
| 241 TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpError) { | 271 TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpError) { |
| 242 SetFakeResponse(/*data=*/std::string(), net::HTTP_NOT_FOUND, | 272 SetFakeResponse(/*data=*/std::string(), net::HTTP_NOT_FOUND, |
| 243 net::URLRequestStatus::SUCCESS); | 273 net::URLRequestStatus::SUCCESS); |
| 244 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); | 274 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); |
| 245 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 275 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 246 RunUntilIdle(); | 276 FastForwardUntilNoTasksRemain(); |
| 247 EXPECT_THAT(snippets_fetcher().last_status(), Eq("HTTP error 404")); | 277 EXPECT_THAT(snippets_fetcher().last_status(), Eq("HTTP error 404")); |
| 248 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); | 278 EXPECT_THAT(snippets_fetcher().last_json(), IsEmpty()); |
| 249 EXPECT_THAT( | 279 EXPECT_THAT( |
| 250 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 280 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 251 ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); | 281 ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); |
| 252 EXPECT_THAT(histogram_tester().GetAllSamples( | 282 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 253 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 283 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 254 ElementsAre(base::Bucket(/*min=*/404, /*count=*/1))); | 284 ElementsAre(base::Bucket(/*min=*/404, /*count=*/1))); |
| 285 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 286 Not(IsEmpty())); |
| 255 } | 287 } |
| 256 | 288 |
| 257 TEST_F(NTPSnippetsFetcherTest, ShouldReportJsonError) { | 289 TEST_F(NTPSnippetsFetcherTest, ShouldReportJsonError) { |
| 258 const std::string kInvalidJsonStr = "{ \"recos\": []"; | 290 const std::string kInvalidJsonStr = "{ \"recos\": []"; |
| 259 SetFakeResponse(/*data=*/kInvalidJsonStr, net::HTTP_OK, | 291 SetFakeResponse(/*data=*/kInvalidJsonStr, net::HTTP_OK, |
| 260 net::URLRequestStatus::SUCCESS); | 292 net::URLRequestStatus::SUCCESS); |
| 261 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); | 293 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); |
| 262 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 294 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 263 RunUntilIdle(); | 295 FastForwardUntilNoTasksRemain(); |
| 264 EXPECT_THAT(snippets_fetcher().last_status(), | 296 EXPECT_THAT(snippets_fetcher().last_status(), |
| 265 StartsWith("Received invalid JSON (error ")); | 297 StartsWith("Received invalid JSON (error ")); |
| 266 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kInvalidJsonStr)); | 298 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kInvalidJsonStr)); |
| 267 EXPECT_THAT( | 299 EXPECT_THAT( |
| 268 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 300 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 269 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); | 301 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); |
| 270 EXPECT_THAT(histogram_tester().GetAllSamples( | 302 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 271 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 303 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 272 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 304 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 305 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 306 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 307 /*count=*/1))); |
| 273 } | 308 } |
| 274 | 309 |
| 275 TEST_F(NTPSnippetsFetcherTest, ShouldReportJsonErrorForEmptyResponse) { | 310 TEST_F(NTPSnippetsFetcherTest, ShouldReportJsonErrorForEmptyResponse) { |
| 276 SetFakeResponse(/*data=*/std::string(), net::HTTP_OK, | 311 SetFakeResponse(/*data=*/std::string(), net::HTTP_OK, |
| 277 net::URLRequestStatus::SUCCESS); | 312 net::URLRequestStatus::SUCCESS); |
| 278 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); | 313 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); |
| 279 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 314 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 280 RunUntilIdle(); | 315 FastForwardUntilNoTasksRemain(); |
| 281 EXPECT_THAT(snippets_fetcher().last_status(), | 316 EXPECT_THAT(snippets_fetcher().last_status(), |
| 282 StartsWith("Received invalid JSON (error ")); | 317 StartsWith("Received invalid JSON (error ")); |
| 283 EXPECT_THAT(snippets_fetcher().last_json(), std::string()); | 318 EXPECT_THAT(snippets_fetcher().last_json(), std::string()); |
| 284 EXPECT_THAT( | 319 EXPECT_THAT( |
| 285 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 320 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 286 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); | 321 ElementsAre(base::Bucket(/*min=*/4, /*count=*/1))); |
| 287 EXPECT_THAT(histogram_tester().GetAllSamples( | 322 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 288 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 323 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 289 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 324 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 290 } | 325 } |
| 291 | 326 |
| 292 TEST_F(NTPSnippetsFetcherTest, ShouldReportInvalidListError) { | 327 TEST_F(NTPSnippetsFetcherTest, ShouldReportInvalidListError) { |
| 293 const std::string kJsonStr = | 328 const std::string kJsonStr = |
| 294 "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}"; | 329 "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}"; |
| 295 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, | 330 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, |
| 296 net::URLRequestStatus::SUCCESS); | 331 net::URLRequestStatus::SUCCESS); |
| 297 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); | 332 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); |
| 298 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 333 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 299 RunUntilIdle(); | 334 FastForwardUntilNoTasksRemain(); |
| 300 EXPECT_THAT(snippets_fetcher().last_status(), Eq("Invalid / empty list.")); | 335 EXPECT_THAT(snippets_fetcher().last_status(), Eq("Invalid / empty list.")); |
| 301 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); | 336 EXPECT_THAT(snippets_fetcher().last_json(), Eq(kJsonStr)); |
| 302 EXPECT_THAT( | 337 EXPECT_THAT( |
| 303 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 338 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 304 ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); | 339 ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); |
| 305 EXPECT_THAT(histogram_tester().GetAllSamples( | 340 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 306 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 341 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 307 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 342 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 343 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 344 Not(IsEmpty())); |
| 308 } | 345 } |
| 309 | 346 |
| 310 // This test actually verifies that the test setup itself is sane, to prevent | 347 // This test actually verifies that the test setup itself is sane, to prevent |
| 311 // hard-to-reproduce test failures. | 348 // hard-to-reproduce test failures. |
| 312 TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpErrorForMissingBakedResponse) { | 349 TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpErrorForMissingBakedResponse) { |
| 313 InitFakeURLFetcherFactory(); | 350 InitFakeURLFetcherFactory(); |
| 314 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); | 351 EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1); |
| 315 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 352 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 316 RunUntilIdle(); | 353 FastForwardUntilNoTasksRemain(); |
| 317 } | 354 } |
| 318 | 355 |
| 319 TEST_F(NTPSnippetsFetcherTest, ShouldCancelOngoingFetch) { | 356 TEST_F(NTPSnippetsFetcherTest, ShouldCancelOngoingFetch) { |
| 320 const std::string kJsonStr = "{ \"recos\": [] }"; | 357 const std::string kJsonStr = "{ \"recos\": [] }"; |
| 321 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, | 358 SetFakeResponse(/*data=*/kJsonStr, net::HTTP_OK, |
| 322 net::URLRequestStatus::SUCCESS); | 359 net::URLRequestStatus::SUCCESS); |
| 323 EXPECT_CALL(mock_callback(), Run(/*snippets=*/PointeeSizeIs(0))).Times(1); | 360 EXPECT_CALL(mock_callback(), Run(/*snippets=*/PointeeSizeIs(0))).Times(1); |
| 324 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 361 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 325 // Second call to FetchSnippetsFromHosts() overrides/cancels the previous. | 362 // Second call to FetchSnippetsFromHosts() overrides/cancels the previous. |
| 326 // Callback is expected to be called once. | 363 // Callback is expected to be called once. |
| 327 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); | 364 snippets_fetcher().FetchSnippetsFromHosts(test_hosts(), /*count=*/1); |
| 328 RunUntilIdle(); | 365 FastForwardUntilNoTasksRemain(); |
| 329 EXPECT_THAT( | 366 EXPECT_THAT( |
| 330 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), | 367 histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchResult"), |
| 331 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); | 368 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1))); |
| 332 EXPECT_THAT(histogram_tester().GetAllSamples( | 369 EXPECT_THAT(histogram_tester().GetAllSamples( |
| 333 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), | 370 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode"), |
| 334 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); | 371 ElementsAre(base::Bucket(/*min=*/200, /*count=*/1))); |
| 372 EXPECT_THAT(histogram_tester().GetAllSamples("NewTabPage.Snippets.FetchTime"), |
| 373 ElementsAre(base::Bucket(/*min=*/kTestJsonParsingLatencyMs, |
| 374 /*count=*/1))); |
| 335 } | 375 } |
| 336 | 376 |
| 337 } // namespace | 377 } // namespace |
| 338 } // namespace ntp_snippets | 378 } // namespace ntp_snippets |
| OLD | NEW |