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

Side by Side Diff: components/doodle/doodle_fetcher_unittest.cc

Issue 2660883002: Introduce a Doodle Fetcher for NTP (Closed)
Patch Set: Thread-safe multiple callbacks. Weak tests. Created 3 years, 10 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
(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/doodle/doodle_fetcher.h"
6
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/files/file_util.h"
13 #include "base/files/important_file_writer.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/json/json_reader.h"
16 #include "base/json/json_writer.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/run_loop.h"
19 #include "base/test/sequenced_worker_pool_owner.h"
20 #include "base/test/test_mock_time_task_runner.h"
21 #include "base/threading/sequenced_task_runner_handle.h"
22 #include "base/threading/thread_task_runner_handle.h"
23 #include "base/values.h"
24 #include "components/safe_json/testing_json_parser.h"
25 #include "net/http/http_status_code.h"
26 #include "net/url_request/test_url_fetcher_factory.h"
27 #include "net/url_request/url_request_status.h"
28 #include "net/url_request/url_request_test_util.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 using testing::Eq;
33 using testing::IsEmpty;
34
35 namespace doodle {
36
37 namespace {
38
39 const char* kSampleResponse =
40 ")]}'{"
Marc Treib 2017/02/01 10:55:58 You could use a raw string literal here, to avoid
fhorschig 2017/02/01 11:16:14 Done.
41 "\"ddljson\": {"
42 " \"alt_text\":\"Mouseover Text\","
43 " \"doodle_type\":\"SIMPLE\","
44 " \"gallery_url\":\"//www.google.com/doodles/burning-man-festival\","
45 " \"header_layout\":\"LEGACY\","
46 " \"hires_image\": {"
47 " \"alternate_url\":\"\","
48 " \"background_color\":\"#ffffff\","
49 " \"height\":450,"
50 " \"image_id\":0,"
51 " \"image_name\":\"\","
52 " \"is_animated_gif\":true,"
53 " \"is_cta\":false,"
54 " \"offset_x\":0,"
55 " \"offset_y\":0,"
56 " \"overlay_icon_color\":\"\","
57 " \"size_type\":\"LARGE_2X\","
58 " \"slot\":8,"
59 " \"url\":\"/logos/doodles/2015/"
60 "new-years-eve-2015-5985438795825152-hp2x.gif\","
61 " \"width\":978"
62 " },"
63 " \"id\":0,"
64 " \"intent\":\"BUILTIN\","
65 " \"large_image\": {"
66 " \"alternate_url\":\"\","
67 " \"background_color\":\"#ffffff\","
68 " \"height\":225,"
69 " \"image_id\":0,"
70 " \"image_name\":\"\","
71 " \"is_animated_gif\":true,"
72 " \"is_cta\":false,"
73 " \"offset_x\":0,"
74 " \"offset_y\":0,"
75 " \"overlay_icon_color\":\"\","
76 " \"size_type\":\"LARGE\","
77 " \"slot\":1,"
78 " \"url\":\"/logos/doodles/2015/"
79 "new-years-eve-2015-5985438795825152-hp.gif\","
80 " \"width\":489"
81 " },"
82 " \"medium_image\": {"
83 " \"alternate_url\":\"\","
84 " \"background_color\":\"#fff1b9\","
85 " \"height\":128,"
86 " \"image_id\":0,"
87 " \"image_name\":\"\","
88 " \"is_animated_gif\":false,"
89 " \"is_cta\":true,"
90 " \"offset_x\":0,"
91 " \"offset_y\":0,"
92 " \"overlay_icon_color\":\"#ff0f15\","
93 " \"size_type\":\"LARGE_MOBILE_SRP\","
94 " \"slot\":3,"
95 " \"url\":\"/logos/doodles/2015/new-years-eve-2015-5985438795825152-m.pn"
96 "g\","
97 " \"width\":291"
98 " },"
99 " \"search_url\":\"/search?q\u003dtest\","
100 " \"share_text\":\"Share Text #GoogleDoodle\nhttps://g.co/doodle/8hfqzq\","
101 " \"short_link\":\"//g.co/doodle/8hfqzq\","
102 " \"show_now_header_search_affordance\":false,"
103 " \"show_now_header_share_button\":true,"
104 " \"small_image\": {"
105 " \"alternate_url\":\"\","
106 " \"background_color\":\"\","
107 " \"height\":41,"
108 " \"image_id\":0,"
109 " \"image_name\":\"\","
110 " \"is_animated_gif\":false,"
111 " \"is_cta\":false,"
112 " \"offset_x\":0,"
113 " \"offset_y\":0,"
114 " \"overlay_icon_color\":\"\","
115 " \"size_type\":\"SMALL_DESKTOP_SRP\","
116 " \"slot\":4,"
117 " \"url\":\"/logos/doodles/2015/"
118 "new-years-eve-2015-5985438795825152.2-res.png\","
119 " \"width\":95"
120 " },"
121 " \"target_url\":\"/search?q\u003dtest\u0026sa\u003dX\u0026ved\u003d0ahUKE"
122 "wjm9vmF8enRAhUJvBQKHX1CC54QNggB\","
123 " \"time_to_live_ms\":514220215000,"
124 " \"transparent_large_image\": {"
125 " \"alternate_url\":\"\","
126 " \"background_color\":\"\","
127 " \"height\":225,"
128 " \"image_id\":0,"
129 " \"image_name\":\"\","
130 " \"is_animated_gif\":false,"
131 " \"is_cta\":false,"
132 " \"offset_x\":0,"
133 " \"offset_y\":0,"
134 " \"overlay_icon_color\":\"\","
135 " \"size_type\":\"LARGE\","
136 " \"slot\":2,"
137 " \"url\":\"/logos/doodles/2015/"
138 "new-years-eve-2015-5985438795825152-thp.png\","
139 " \"width\":510"
140 " }"
141 "}}";
142
143 const char kBaseUrl[] = "https://www.google.com/";
144
145 std::string AbsoluteUrl(const std::string& relative_url) {
146 return GURL(kBaseUrl).Resolve(relative_url).spec();
147 }
148
149 } // namespace
150
151 class DoodleFetcherTest : public ::testing::Test {
152 public:
153 DoodleFetcherTest()
154 : url_(GURL(kBaseUrl).Resolve(kDoodleConfigUrl)),
155 url_fetcher_factory_(nullptr),
156 mock_task_runner_(new base::TestMockTimeTaskRunner()),
157 mock_task_runner_handle_(mock_task_runner_),
158 context_getter(
159 new net::TestURLRequestContextGetter(mock_task_runner_.get())) {
160 // Random difference to 0 ensures that expiry_dates are really relative.
161 mock_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(80082));
162 }
163
164 void RespondWithData(const std::string& data) {
165 url_fetcher_factory_.SetFakeResponse(url_, data, net::HTTP_OK,
166 net::URLRequestStatus::SUCCESS);
167 }
168
169 void RespondWithError() {
170 url_fetcher_factory_.SetFakeResponse(url_, "", net::HTTP_NOT_FOUND,
171 net::URLRequestStatus::FAILED);
172 }
173
174 DoodleConfig FetchDoodle() {
175 DoodleConfig doodle(DoodleState::NO_DOODLE);
176 std::unique_ptr<DoodleFetcher> fetcher = CreateDoodleFetcher();
177 TriggerFetch(fetcher.get(), &doodle);
178 WaitForCallbacks();
179 return doodle;
180 }
181
182 std::unique_ptr<DoodleFetcher> CreateDoodleFetcher() {
183 std::unique_ptr<DoodleFetcher> fetcher =
184 base::MakeUnique<DoodleFetcher>(context_getter.get(), GURL(kBaseUrl));
185 fetcher->SetClockForTesting(mock_task_runner_->GetMockClock());
186 return fetcher;
187 }
188
189 void TriggerFetch(DoodleFetcher* fetcher, DoodleConfig* response) {
190 fetcher->FetchDoodle(base::BindOnce(
191 [](DoodleConfig* doodle, const DoodleConfig& config) {
192 *doodle = std::move(config);
193 },
194 response));
195 }
196
197 base::Time TimeFromNow(uint64_t milliseconds) {
198 return mock_task_runner_->GetMockClock()->Now() +
199 base::TimeDelta::FromMilliseconds(milliseconds);
200 }
201
202 void WaitForCallbacks() {
203 mock_task_runner_->FastForwardUntilNoTasksRemain();
204 }
205
206 private:
207 GURL url_;
208 net::FakeURLFetcherFactory url_fetcher_factory_;
209 scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
210 base::ThreadTaskRunnerHandle mock_task_runner_handle_;
211 scoped_refptr<net::TestURLRequestContextGetter> context_getter;
212 safe_json::TestingJsonParser::ScopedFactoryOverride factory_override;
213 };
214
215 TEST_F(DoodleFetcherTest, ReturnsFromFetchWithoutError) {
216 RespondWithData(kSampleResponse);
217
218 EXPECT_THAT(FetchDoodle().state, Eq(DoodleState::AVAILABLE));
219 }
220
221 TEST_F(DoodleFetcherTest, ReturnsFrom404FetchWithError) {
222 RespondWithError();
223
224 EXPECT_THAT(FetchDoodle().state, Eq(DoodleState::DOWNLOAD_ERROR));
225 }
226
227 TEST_F(DoodleFetcherTest, ReturnsErrorForInvalidJson) {
228 RespondWithData("{}");
229
230 EXPECT_THAT(FetchDoodle().state, Eq(DoodleState::PARSING_ERROR));
231 }
232
233 TEST_F(DoodleFetcherTest, ResponseContainsValidBaseInformation) {
234 RespondWithData(kSampleResponse);
235
236 DoodleConfig response = FetchDoodle();
237
238 EXPECT_TRUE(response.search_url.is_valid());
239 EXPECT_THAT(response.search_url, Eq(AbsoluteUrl("/search?q\u003dtest")));
240 EXPECT_THAT(response.fullpage_interactive_url, Eq(GURL()));
241 EXPECT_TRUE(response.target_url.is_valid());
242 EXPECT_THAT(response.target_url,
243 Eq(AbsoluteUrl("/search?q\u003dtest\u0026sa\u003dX\u0026ved\u003d"
244 "0ahUKEwjm9vmF8enRAhUJvBQKHX1CC54QNggB")));
245 EXPECT_THAT(response.doodle_type, Eq(DoodleType::SIMPLE));
246 EXPECT_THAT(response.alt_text, Eq("Mouseover Text"));
247
248 EXPECT_THAT(response.expiry_date, Eq(TimeFromNow(514220215000)));
249 }
250
251 TEST_F(DoodleFetcherTest, EmptyResponsesYieldEmptyUrlsAndNoDoodleState) {
252 RespondWithData("{\"ddljson\":{}}");
253
254 DoodleConfig response = FetchDoodle();
255
256 EXPECT_THAT(response.state, Eq(DoodleState::NO_DOODLE));
257
258 EXPECT_FALSE(response.search_url.is_valid());
259 EXPECT_THAT(response.search_url, Eq(GURL()));
260
261 EXPECT_FALSE(response.fullpage_interactive_url.is_valid());
262 EXPECT_THAT(response.fullpage_interactive_url, Eq(GURL()));
263
264 EXPECT_FALSE(response.target_url.is_valid());
265 EXPECT_THAT(response.target_url, Eq(GURL()));
266
267 EXPECT_FALSE(response.small_image.url.is_valid());
268 EXPECT_THAT(response.small_image.url, Eq(GURL()));
269 EXPECT_FALSE(response.medium_image.url.is_valid());
270 EXPECT_THAT(response.medium_image.url, Eq(GURL()));
271 EXPECT_FALSE(response.hires_image.url.is_valid());
272 EXPECT_THAT(response.hires_image.url, Eq(GURL()));
273 EXPECT_FALSE(response.large_image.url.is_valid());
274 EXPECT_THAT(response.large_image.url, Eq(GURL()));
275 EXPECT_FALSE(response.transparent_large_image.url.is_valid());
276 EXPECT_THAT(response.transparent_large_image.url, Eq(GURL()));
277 }
278
279 TEST_F(DoodleFetcherTest, ResponseContainsExactlyTheSampleImages) {
280 RespondWithData(kSampleResponse);
281
282 DoodleConfig response = FetchDoodle();
283
284 EXPECT_TRUE(response.small_image.url.is_valid());
285 EXPECT_THAT(response.small_image.url.spec(),
286 Eq(AbsoluteUrl("/logos/doodles/2015/new-years-eve-2015-5985438795"
287 "825152.2-res.png")));
288 EXPECT_THAT(response.small_image.width, Eq(95));
289 EXPECT_THAT(response.small_image.height, Eq(41));
290 EXPECT_THAT(response.small_image.background_color, Eq(""));
291 EXPECT_FALSE(response.small_image.is_animated_gif);
292 EXPECT_FALSE(response.small_image.is_cta);
293
294 EXPECT_TRUE(response.medium_image.url.is_valid());
295 EXPECT_THAT(response.medium_image.url.spec(),
296 Eq(AbsoluteUrl("/logos/doodles/2015/new-years-eve-2015-5985438795"
297 "825152-m.png")));
298 EXPECT_THAT(response.medium_image.width, Eq(291));
299 EXPECT_THAT(response.medium_image.height, Eq(128));
300 EXPECT_THAT(response.medium_image.background_color, Eq("#fff1b9"));
301 EXPECT_FALSE(response.medium_image.is_animated_gif);
302 EXPECT_TRUE(response.medium_image.is_cta);
303
304 EXPECT_TRUE(response.transparent_large_image.url.is_valid());
305 EXPECT_THAT(response.transparent_large_image.url.spec(),
306 Eq(AbsoluteUrl("/logos/doodles/2015/new-years-eve-2015-5985438795"
307 "825152-thp.png")));
308 EXPECT_THAT(response.transparent_large_image.width, Eq(510));
309 EXPECT_THAT(response.transparent_large_image.height, Eq(225));
310 EXPECT_THAT(response.transparent_large_image.background_color, Eq(""));
311 EXPECT_FALSE(response.transparent_large_image.is_animated_gif);
312 EXPECT_FALSE(response.transparent_large_image.is_cta);
313
314 EXPECT_TRUE(response.large_image.url.is_valid());
315 EXPECT_THAT(response.large_image.url.spec(),
316 Eq(AbsoluteUrl("/logos/doodles/2015/new-years-eve-2015-5985438795"
317 "825152-hp.gif")));
318 EXPECT_THAT(response.large_image.width, Eq(489));
319 EXPECT_THAT(response.large_image.height, Eq(225));
320 EXPECT_THAT(response.large_image.background_color, Eq("#ffffff"));
321 EXPECT_TRUE(response.large_image.is_animated_gif);
322 EXPECT_FALSE(response.large_image.is_cta);
323
324 EXPECT_TRUE(response.hires_image.url.is_valid());
325 EXPECT_THAT(response.hires_image.url.spec(),
326 Eq(AbsoluteUrl("/logos/doodles/2015/new-years-eve-2015-5985438795"
327 "825152-hp2x.gif")));
328 EXPECT_THAT(response.hires_image.width, Eq(978));
329 EXPECT_THAT(response.hires_image.height, Eq(450));
330 EXPECT_THAT(response.hires_image.background_color, Eq("#ffffff"));
331 EXPECT_TRUE(response.hires_image.is_animated_gif);
332 EXPECT_FALSE(response.hires_image.is_cta);
333 }
334
335 TEST_F(DoodleFetcherTest, RespondsToMultipleRequestsWithSameResponse) {
336 RespondWithData(kSampleResponse);
337
338 DoodleConfig doodle1(DoodleState::NO_DOODLE);
339 DoodleConfig doodle2(DoodleState::NO_DOODLE);
340 std::unique_ptr<DoodleFetcher> fetcher = CreateDoodleFetcher();
341
342 TriggerFetch(fetcher.get(), &doodle1);
343 TriggerFetch(fetcher.get(), &doodle2);
344
345 WaitForCallbacks();
346 // ASSERT!
347 }
348
349 } // namespace doodle
OLDNEW
« components/doodle/doodle_fetcher.cc ('K') | « components/doodle/doodle_fetcher.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698