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

Side by Side Diff: components/ntp_snippets/ntp_snippets_fetcher_unittest.cc

Issue 1961943002: [NTP Snippets] Add histogram with fetch time (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@json_to_fetcher_5
Patch Set: Rebased. Created 4 years, 7 months 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
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/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
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
OLDNEW
« no previous file with comments | « components/ntp_snippets/ntp_snippets_fetcher.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698