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

Side by Side Diff: components/suggestions/suggestions_service_unittest.cc

Issue 2568133005: [SuggestionsService] Split SuggestionsService interface from impl (Closed)
Patch Set: Moved impl to dedicated file. Created 4 years 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 2014 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/suggestions/suggestions_service.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/feature_list.h"
14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/run_loop.h"
17 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
18 #include "components/suggestions/blacklist_store.h"
19 #include "components/suggestions/image_manager.h"
20 #include "components/suggestions/proto/suggestions.pb.h"
21 #include "components/suggestions/suggestions_store.h"
22 #include "components/sync/driver/fake_sync_service.h"
23 #include "components/sync/driver/sync_service.h"
24 #include "net/base/escape.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/http/http_status_code.h"
27 #include "net/url_request/test_url_fetcher_factory.h"
28 #include "net/url_request/url_request_status.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "ui/gfx/image/image.h"
33
34 using testing::DoAll;
35 using ::testing::AnyNumber;
36 using ::testing::Eq;
37 using ::testing::Return;
38 using testing::SetArgPointee;
39 using ::testing::NiceMock;
40 using ::testing::StrictMock;
41 using ::testing::_;
42
43 namespace {
44
45 // SuggestionsService::AccessTokenFetcher provides an empty account ID if its
46 // SigninManager is null.
47 const char kAccountId[] = "";
48 const char kTestTitle[] = "a title";
49 const char kTestUrl[] = "http://go.com";
50 const char kTestFaviconUrl[] =
51 "https://s2.googleusercontent.com/s2/favicons?domain_url="
52 "http://go.com&alt=s&sz=32";
53 const char kBlacklistedUrl[] = "http://blacklist.com";
54 const char kBlacklistedUrlAlt[] = "http://blacklist-atl.com";
55 const int64_t kTestDefaultExpiry = 1402200000000000;
56 const int64_t kTestSetExpiry = 1404792000000000;
57
58 std::unique_ptr<net::FakeURLFetcher> CreateURLFetcher(
59 const GURL& url,
60 net::URLFetcherDelegate* delegate,
61 const std::string& response_data,
62 net::HttpStatusCode response_code,
63 net::URLRequestStatus::Status status) {
64 std::unique_ptr<net::FakeURLFetcher> fetcher(new net::FakeURLFetcher(
65 url, delegate, response_data, response_code, status));
66
67 if (response_code == net::HTTP_OK) {
68 scoped_refptr<net::HttpResponseHeaders> download_headers(
69 new net::HttpResponseHeaders(""));
70 download_headers->AddHeader("Content-Type: text/html");
71 fetcher->set_response_headers(download_headers);
72 }
73 return fetcher;
74 }
75
76 // GMock matcher for protobuf equality.
77 MATCHER_P(EqualsProto, message, "") {
78 // This implementation assumes protobuf serialization is deterministic, which
79 // is true in practice but technically not something that code is supposed
80 // to rely on. However, it vastly simplifies the implementation.
81 std::string expected_serialized, actual_serialized;
82 message.SerializeToString(&expected_serialized);
83 arg.SerializeToString(&actual_serialized);
84 return expected_serialized == actual_serialized;
85 }
86
87 } // namespace
88
89 namespace suggestions {
90
91 SuggestionsProfile CreateSuggestionsProfile() {
92 SuggestionsProfile profile;
93 profile.set_timestamp(123);
94 ChromeSuggestion* suggestion = profile.add_suggestions();
95 suggestion->set_title(kTestTitle);
96 suggestion->set_url(kTestUrl);
97 suggestion->set_expiry_ts(kTestSetExpiry);
98 return profile;
99 }
100
101 // Creates one suggestion with expiry timestamp and one without.
102 SuggestionsProfile CreateSuggestionsProfileWithExpiryTimestamps() {
103 SuggestionsProfile profile;
104 profile.set_timestamp(123);
105 ChromeSuggestion* suggestion = profile.add_suggestions();
106 suggestion->set_title(kTestTitle);
107 suggestion->set_url(kTestUrl);
108 suggestion->set_expiry_ts(kTestSetExpiry);
109
110 suggestion = profile.add_suggestions();
111 suggestion->set_title(kTestTitle);
112 suggestion->set_url(kTestUrl);
113
114 return profile;
115 }
116
117 class MockSyncService : public syncer::FakeSyncService {
118 public:
119 MockSyncService() {}
120 virtual ~MockSyncService() {}
121 MOCK_CONST_METHOD0(CanSyncStart, bool());
122 MOCK_CONST_METHOD0(IsSyncActive, bool());
123 MOCK_CONST_METHOD0(ConfigurationDone, bool());
124 MOCK_CONST_METHOD0(GetActiveDataTypes, syncer::ModelTypeSet());
125 };
126
127 class TestSuggestionsStore : public suggestions::SuggestionsStore {
128 public:
129 TestSuggestionsStore() {
130 cached_suggestions = CreateSuggestionsProfile();
131 }
132 bool LoadSuggestions(SuggestionsProfile* suggestions) override {
133 suggestions->CopyFrom(cached_suggestions);
134 return cached_suggestions.suggestions_size();
135 }
136 bool StoreSuggestions(const SuggestionsProfile& suggestions) override {
137 cached_suggestions.CopyFrom(suggestions);
138 return true;
139 }
140 void ClearSuggestions() override {
141 cached_suggestions = SuggestionsProfile();
142 }
143
144 SuggestionsProfile cached_suggestions;
145 };
146
147 class MockImageManager : public suggestions::ImageManager {
148 public:
149 MockImageManager() {}
150 virtual ~MockImageManager() {}
151 MOCK_METHOD1(Initialize, void(const SuggestionsProfile&));
152 MOCK_METHOD2(GetImageForURL,
153 void(const GURL&,
154 base::Callback<void(const GURL&, const gfx::Image&)>));
155 MOCK_METHOD2(AddImageURL, void(const GURL&, const GURL&));
156 };
157
158 class MockBlacklistStore : public suggestions::BlacklistStore {
159 public:
160 MOCK_METHOD1(BlacklistUrl, bool(const GURL&));
161 MOCK_METHOD0(IsEmpty, bool());
162 MOCK_METHOD1(GetTimeUntilReadyForUpload, bool(base::TimeDelta*));
163 MOCK_METHOD2(GetTimeUntilURLReadyForUpload,
164 bool(const GURL&, base::TimeDelta*));
165 MOCK_METHOD1(GetCandidateForUpload, bool(GURL*));
166 MOCK_METHOD1(RemoveUrl, bool(const GURL&));
167 MOCK_METHOD1(FilterSuggestions, void(SuggestionsProfile*));
168 MOCK_METHOD0(ClearBlacklist, void());
169 };
170
171 class SuggestionsServiceTest : public testing::Test {
172 public:
173 void CheckCallback(const SuggestionsProfile& suggestions_profile) {
174 ++suggestions_data_callback_count_;
175 if (suggestions_profile.suggestions_size() == 0)
176 ++suggestions_empty_data_count_;
177 }
178
179 void CheckSuggestionsData() {
180 SuggestionsProfile suggestions_profile;
181 test_suggestions_store_->LoadSuggestions(&suggestions_profile);
182 EXPECT_EQ(1, suggestions_profile.suggestions_size());
183 EXPECT_EQ(kTestTitle, suggestions_profile.suggestions(0).title());
184 EXPECT_EQ(kTestUrl, suggestions_profile.suggestions(0).url());
185 EXPECT_EQ(kTestFaviconUrl,
186 suggestions_profile.suggestions(0).favicon_url());
187 }
188
189 int suggestions_data_callback_count_;
190 int suggestions_empty_data_count_;
191 bool blacklisting_failed_;
192 bool undo_blacklisting_failed_;
193
194 protected:
195 SuggestionsServiceTest()
196 : suggestions_data_callback_count_(0),
197 suggestions_empty_data_count_(0),
198 blacklisting_failed_(false),
199 undo_blacklisting_failed_(false),
200 factory_(nullptr, base::Bind(&CreateURLFetcher)),
201 mock_sync_service_(nullptr),
202 mock_thumbnail_manager_(nullptr),
203 mock_blacklist_store_(nullptr),
204 test_suggestions_store_(nullptr) {
205 token_service_.UpdateCredentials(kAccountId, "refresh_token");
206 token_service_.set_auto_post_fetch_response_on_message_loop(true);
207 }
208
209 ~SuggestionsServiceTest() override {}
210
211 void SetUp() override {
212 request_context_ =
213 new net::TestURLRequestContextGetter(io_message_loop_.task_runner());
214 }
215
216 SuggestionsService* CreateSuggestionsServiceWithMocks() {
217 mock_sync_service_.reset(new MockSyncService);
218 ON_CALL(*mock_sync_service_, CanSyncStart()).WillByDefault(Return(true));
219 ON_CALL(*mock_sync_service_, IsSyncActive()).WillByDefault(Return(true));
220 ON_CALL(*mock_sync_service_, ConfigurationDone())
221 .WillByDefault(Return(true));
222 ON_CALL(*mock_sync_service_, GetActiveDataTypes())
223 .WillByDefault(
224 Return(syncer::ModelTypeSet(syncer::HISTORY_DELETE_DIRECTIVES)));
225
226 // These objects are owned by the returned SuggestionsService, but we keep
227 // the pointer around for testing.
228 test_suggestions_store_ = new TestSuggestionsStore();
229 mock_thumbnail_manager_ = new StrictMock<MockImageManager>();
230 mock_blacklist_store_ = new StrictMock<MockBlacklistStore>();
231 return new SuggestionsService(
232 nullptr /* signin_manager */, &token_service_, mock_sync_service_.get(),
233 request_context_.get(), base::WrapUnique(test_suggestions_store_),
234 base::WrapUnique(mock_thumbnail_manager_),
235 base::WrapUnique(mock_blacklist_store_));
236 }
237
238 void Blacklist(SuggestionsService* suggestions_service, GURL url) {
239 blacklisting_failed_ = !suggestions_service->BlacklistURL(url);
240 }
241
242 void UndoBlacklist(SuggestionsService* suggestions_service, GURL url) {
243 undo_blacklisting_failed_ = !suggestions_service->UndoBlacklistURL(url);
244 }
245
246 // Helper for Undo failure tests. Depending on |is_uploaded|, tests either
247 // the case where the URL is no longer in the local blacklist or the case
248 // in which it's not yet candidate for upload.
249 void UndoBlacklistURLFailsHelper(bool is_uploaded) {
250 std::unique_ptr<SuggestionsService> suggestions_service(
251 CreateSuggestionsServiceWithMocks());
252 EXPECT_TRUE(suggestions_service != nullptr);
253 // Ensure scheduling the request doesn't happen before undo.
254 base::TimeDelta delay = base::TimeDelta::FromHours(1);
255 suggestions_service->set_blacklist_delay(delay);
256
257 auto subscription = suggestions_service->AddCallback(base::Bind(
258 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
259
260 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
261 GURL blacklisted_url(kBlacklistedUrl);
262
263 // Blacklist expectations.
264 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
265 .WillOnce(Return(true));
266 EXPECT_CALL(*mock_thumbnail_manager_,
267 Initialize(EqualsProto(suggestions_profile)));
268 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_));
269 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
270 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
271 // Undo expectations.
272 if (is_uploaded) {
273 // URL is not in local blacklist.
274 EXPECT_CALL(*mock_blacklist_store_,
275 GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _))
276 .WillOnce(Return(false));
277 } else {
278 // URL is not yet candidate for upload.
279 base::TimeDelta negative_delay = base::TimeDelta::FromHours(-1);
280 EXPECT_CALL(*mock_blacklist_store_,
281 GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _))
282 .WillOnce(DoAll(SetArgPointee<1>(negative_delay), Return(true)));
283 }
284
285 Blacklist(suggestions_service.get(), blacklisted_url);
286 UndoBlacklist(suggestions_service.get(), blacklisted_url);
287
288 EXPECT_EQ(1, suggestions_data_callback_count_);
289 EXPECT_FALSE(blacklisting_failed_);
290 EXPECT_TRUE(undo_blacklisting_failed_);
291 }
292
293 bool HasPendingSuggestionsRequest(SuggestionsService* suggestions_service) {
294 return !!suggestions_service->pending_request_.get();
295 }
296
297 protected:
298 base::MessageLoopForIO io_message_loop_;
299 net::FakeURLFetcherFactory factory_;
300 FakeProfileOAuth2TokenService token_service_;
301 std::unique_ptr<MockSyncService> mock_sync_service_;
302 // Only used if the SuggestionsService is built with mocks. Not owned.
303 MockImageManager* mock_thumbnail_manager_;
304 MockBlacklistStore* mock_blacklist_store_;
305 TestSuggestionsStore* test_suggestions_store_;
306 scoped_refptr<net::TestURLRequestContextGetter> request_context_;
307
308 private:
309 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest);
310 };
311
312 TEST_F(SuggestionsServiceTest, FetchSuggestionsData) {
313 std::unique_ptr<SuggestionsService> suggestions_service(
314 CreateSuggestionsServiceWithMocks());
315 ASSERT_TRUE(suggestions_service != nullptr);
316 auto subscription = suggestions_service->AddCallback(base::Bind(
317 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
318
319 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
320
321 // Set up net::FakeURLFetcherFactory.
322 factory_.SetFakeResponse(SuggestionsService::BuildSuggestionsURL(),
323 suggestions_profile.SerializeAsString(),
324 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
325
326 // Expectations.
327 EXPECT_CALL(*mock_thumbnail_manager_, Initialize(_));
328 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_));
329 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
330 .WillOnce(Return(false));
331
332 // Send the request. The data should be returned to the callback.
333 suggestions_service->FetchSuggestionsData();
334
335 // Let the network request run.
336 base::RunLoop().RunUntilIdle();
337
338 // Ensure that CheckCallback() ran once.
339 EXPECT_EQ(1, suggestions_data_callback_count_);
340
341 CheckSuggestionsData();
342 }
343
344 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) {
345 std::unique_ptr<SuggestionsService> suggestions_service(
346 CreateSuggestionsServiceWithMocks());
347 ASSERT_TRUE(suggestions_service != nullptr);
348 EXPECT_CALL(*mock_sync_service_, IsSyncActive())
349 .WillRepeatedly(Return(false));
350
351 auto subscription = suggestions_service->AddCallback(base::Bind(
352 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
353
354 // Try to fetch suggestions. Since sync is not active, no network request
355 // should be sent.
356 suggestions_service->FetchSuggestionsData();
357
358 // Let any network request run.
359 base::RunLoop().RunUntilIdle();
360
361 // Ensure that CheckCallback() didn't run.
362 EXPECT_EQ(0, suggestions_data_callback_count_);
363
364 // |test_suggestions_store_| should still contain the default values.
365 SuggestionsProfile suggestions;
366 test_suggestions_store_->LoadSuggestions(&suggestions);
367 EXPECT_EQ(CreateSuggestionsProfile().SerializeAsString(),
368 suggestions.SerializeAsString());
369 }
370
371 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncDisabled) {
372 std::unique_ptr<SuggestionsService> suggestions_service(
373 CreateSuggestionsServiceWithMocks());
374 ASSERT_TRUE(suggestions_service != nullptr);
375 EXPECT_CALL(*mock_sync_service_, CanSyncStart())
376 .WillRepeatedly(Return(false));
377
378 auto subscription = suggestions_service->AddCallback(base::Bind(
379 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
380
381 // Tell SuggestionsService that the sync state changed. The cache should be
382 // cleared and empty data returned to the callback.
383 suggestions_service->OnStateChanged();
384
385 // Ensure that CheckCallback ran once with empty data.
386 EXPECT_EQ(1, suggestions_data_callback_count_);
387 EXPECT_EQ(1, suggestions_empty_data_count_);
388
389 // Try to fetch suggestions. Since sync is not active, no network request
390 // should be sent.
391 suggestions_service->FetchSuggestionsData();
392
393 // Let any network request run.
394 base::RunLoop().RunUntilIdle();
395
396 // Ensure that CheckCallback didn't run again.
397 EXPECT_EQ(1, suggestions_data_callback_count_);
398 }
399
400 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoAccessToken) {
401 token_service_.RevokeCredentials(kAccountId);
402
403 std::unique_ptr<SuggestionsService> suggestions_service(
404 CreateSuggestionsServiceWithMocks());
405 ASSERT_TRUE(suggestions_service != nullptr);
406
407 auto subscription = suggestions_service->AddCallback(base::Bind(
408 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
409
410 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
411 .WillOnce(Return(false));
412
413 suggestions_service->FetchSuggestionsData();
414
415 // No network request should be sent.
416 base::RunLoop().RunUntilIdle();
417 EXPECT_FALSE(HasPendingSuggestionsRequest(suggestions_service.get()));
418 EXPECT_EQ(0, suggestions_data_callback_count_);
419 }
420
421 TEST_F(SuggestionsServiceTest, IssueRequestIfNoneOngoingError) {
422 std::unique_ptr<SuggestionsService> suggestions_service(
423 CreateSuggestionsServiceWithMocks());
424 ASSERT_TRUE(suggestions_service != nullptr);
425
426 // Fake a request error.
427 factory_.SetFakeResponse(SuggestionsService::BuildSuggestionsURL(),
428 "irrelevant", net::HTTP_OK,
429 net::URLRequestStatus::FAILED);
430
431 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
432 .WillOnce(Return(false));
433
434 // Send the request. Empty data will be returned to the callback.
435 suggestions_service->IssueRequestIfNoneOngoing(
436 SuggestionsService::BuildSuggestionsURL());
437
438 // (Testing only) wait until suggestion fetch is complete.
439 base::RunLoop().RunUntilIdle();
440 }
441
442 TEST_F(SuggestionsServiceTest, IssueRequestIfNoneOngoingResponseNotOK) {
443 std::unique_ptr<SuggestionsService> suggestions_service(
444 CreateSuggestionsServiceWithMocks());
445 ASSERT_TRUE(suggestions_service != nullptr);
446
447 // Fake a non-200 response code.
448 factory_.SetFakeResponse(SuggestionsService::BuildSuggestionsURL(),
449 "irrelevant", net::HTTP_BAD_REQUEST,
450 net::URLRequestStatus::SUCCESS);
451
452 // Expect that an upload to the blacklist is scheduled.
453 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
454 .WillOnce(Return(false));
455
456 // Send the request. Empty data will be returned to the callback.
457 suggestions_service->IssueRequestIfNoneOngoing(
458 SuggestionsService::BuildSuggestionsURL());
459
460 // (Testing only) wait until suggestion fetch is complete.
461 base::RunLoop().RunUntilIdle();
462
463 // Expect no suggestions in the cache.
464 SuggestionsProfile empty_suggestions;
465 EXPECT_FALSE(test_suggestions_store_->LoadSuggestions(&empty_suggestions));
466 }
467
468 TEST_F(SuggestionsServiceTest, BlacklistURL) {
469 std::unique_ptr<SuggestionsService> suggestions_service(
470 CreateSuggestionsServiceWithMocks());
471 EXPECT_TRUE(suggestions_service != nullptr);
472 base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0);
473 suggestions_service->set_blacklist_delay(no_delay);
474
475 auto subscription = suggestions_service->AddCallback(base::Bind(
476 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
477
478 GURL blacklisted_url(kBlacklistedUrl);
479 GURL request_url(
480 SuggestionsService::BuildSuggestionsBlacklistURL(blacklisted_url));
481 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
482 factory_.SetFakeResponse(request_url,
483 suggestions_profile.SerializeAsString(),
484 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
485 EXPECT_CALL(*mock_thumbnail_manager_, Initialize(_)).Times(2);
486
487 // Expected calls to the blacklist store.
488 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
489 .WillOnce(Return(true));
490 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(2);
491 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
492 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true)))
493 .WillOnce(Return(false));
494 EXPECT_CALL(*mock_blacklist_store_, GetCandidateForUpload(_))
495 .WillOnce(DoAll(SetArgPointee<0>(blacklisted_url), Return(true)));
496 EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url)))
497 .WillOnce(Return(true));
498
499 Blacklist(suggestions_service.get(), blacklisted_url);
500 EXPECT_EQ(1, suggestions_data_callback_count_);
501
502 // Wait on the upload task, the blacklist request and the next blacklist
503 // scheduling task. This only works when the scheduling task is not for future
504 // execution (note how both the SuggestionsService's scheduling delay and the
505 // BlacklistStore's candidacy delay are zero).
506 base::RunLoop().RunUntilIdle();
507
508 EXPECT_EQ(2, suggestions_data_callback_count_);
509 EXPECT_FALSE(blacklisting_failed_);
510 CheckSuggestionsData();
511 }
512
513 TEST_F(SuggestionsServiceTest, BlacklistURLFails) {
514 std::unique_ptr<SuggestionsService> suggestions_service(
515 CreateSuggestionsServiceWithMocks());
516 ASSERT_TRUE(suggestions_service != nullptr);
517
518 auto subscription = suggestions_service->AddCallback(base::Bind(
519 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
520
521 GURL blacklisted_url(kBlacklistedUrl);
522 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
523 .WillOnce(Return(false));
524
525 Blacklist(suggestions_service.get(), blacklisted_url);
526
527 EXPECT_TRUE(blacklisting_failed_);
528 EXPECT_EQ(0, suggestions_data_callback_count_);
529 }
530
531 // Initial blacklist request fails, triggering a second which succeeds.
532 TEST_F(SuggestionsServiceTest, BlacklistURLRequestFails) {
533 std::unique_ptr<SuggestionsService> suggestions_service(
534 CreateSuggestionsServiceWithMocks());
535 ASSERT_TRUE(suggestions_service != nullptr);
536 base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0);
537 suggestions_service->set_blacklist_delay(no_delay);
538
539 auto subscription = suggestions_service->AddCallback(base::Bind(
540 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
541
542 GURL blacklisted_url(kBlacklistedUrl);
543 GURL request_url(
544 SuggestionsService::BuildSuggestionsBlacklistURL(blacklisted_url));
545 GURL blacklisted_url_alt(kBlacklistedUrlAlt);
546 GURL request_url_alt(
547 SuggestionsService::BuildSuggestionsBlacklistURL(blacklisted_url_alt));
548 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
549
550 // Note: we want to set the response for the blacklist URL to first
551 // succeed, then fail. This doesn't seem possible. For simplicity of testing,
552 // we'll pretend the URL changed in the BlacklistStore between the first and
553 // the second request, and adjust expectations accordingly.
554 factory_.SetFakeResponse(request_url, "irrelevant", net::HTTP_OK,
555 net::URLRequestStatus::FAILED);
556 factory_.SetFakeResponse(request_url_alt,
557 suggestions_profile.SerializeAsString(),
558 net::HTTP_OK, net::URLRequestStatus::SUCCESS);
559
560 // Expectations.
561 EXPECT_CALL(*mock_thumbnail_manager_, Initialize(_)).Times(2);
562 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
563 .WillOnce(Return(true));
564 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(2);
565 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
566 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true)))
567 .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true)))
568 .WillOnce(Return(false));
569 EXPECT_CALL(*mock_blacklist_store_, GetCandidateForUpload(_))
570 .WillOnce(DoAll(SetArgPointee<0>(blacklisted_url), Return(true)))
571 .WillOnce(DoAll(SetArgPointee<0>(blacklisted_url_alt), Return(true)));
572 EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url_alt)))
573 .WillOnce(Return(true));
574
575 // Blacklist call, first request attempt.
576 Blacklist(suggestions_service.get(), blacklisted_url);
577 EXPECT_EQ(1, suggestions_data_callback_count_);
578 EXPECT_FALSE(blacklisting_failed_);
579
580 // Wait for the first scheduling, the first request, the second scheduling,
581 // second request and the third scheduling. Again, note that calling
582 // RunUntilIdle on the MessageLoop only works when the task is not posted for
583 // the future.
584 base::RunLoop().RunUntilIdle();
585 CheckSuggestionsData();
586 }
587
588 TEST_F(SuggestionsServiceTest, UndoBlacklistURL) {
589 std::unique_ptr<SuggestionsService> suggestions_service(
590 CreateSuggestionsServiceWithMocks());
591 ASSERT_TRUE(suggestions_service != nullptr);
592 // Ensure scheduling the request doesn't happen before undo.
593 base::TimeDelta delay = base::TimeDelta::FromHours(1);
594 suggestions_service->set_blacklist_delay(delay);
595
596 auto subscription = suggestions_service->AddCallback(base::Bind(
597 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
598
599 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
600 GURL blacklisted_url(kBlacklistedUrl);
601
602 // Blacklist expectations.
603 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
604 .WillOnce(Return(true));
605 EXPECT_CALL(*mock_thumbnail_manager_,
606 Initialize(EqualsProto(suggestions_profile)))
607 .Times(AnyNumber());
608 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_))
609 .Times(AnyNumber());
610 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
611 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
612 // Undo expectations.
613 EXPECT_CALL(*mock_blacklist_store_,
614 GetTimeUntilURLReadyForUpload(Eq(blacklisted_url), _))
615 .WillOnce(DoAll(SetArgPointee<1>(delay), Return(true)));
616 EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklisted_url)))
617 .WillOnce(Return(true));
618
619 Blacklist(suggestions_service.get(), blacklisted_url);
620 UndoBlacklist(suggestions_service.get(), blacklisted_url);
621
622 EXPECT_EQ(2, suggestions_data_callback_count_);
623 EXPECT_FALSE(blacklisting_failed_);
624 EXPECT_FALSE(undo_blacklisting_failed_);
625 }
626
627 TEST_F(SuggestionsServiceTest, ClearBlacklist) {
628 std::unique_ptr<SuggestionsService> suggestions_service(
629 CreateSuggestionsServiceWithMocks());
630 ASSERT_TRUE(suggestions_service != nullptr);
631 // Ensure scheduling the request doesn't happen before undo.
632 base::TimeDelta delay = base::TimeDelta::FromHours(1);
633 suggestions_service->set_blacklist_delay(delay);
634
635 auto subscription = suggestions_service->AddCallback(base::Bind(
636 &SuggestionsServiceTest::CheckCallback, base::Unretained(this)));
637
638 SuggestionsProfile suggestions_profile = CreateSuggestionsProfile();
639 GURL blacklisted_url(kBlacklistedUrl);
640
641 factory_.SetFakeResponse(
642 SuggestionsService::BuildSuggestionsBlacklistClearURL(),
643 suggestions_profile.SerializeAsString(), net::HTTP_OK,
644 net::URLRequestStatus::SUCCESS);
645
646 // Blacklist expectations.
647 EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklisted_url)))
648 .WillOnce(Return(true));
649 EXPECT_CALL(*mock_thumbnail_manager_,
650 Initialize(EqualsProto(suggestions_profile)))
651 .Times(AnyNumber());
652 EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(AnyNumber());
653 EXPECT_CALL(*mock_blacklist_store_, GetTimeUntilReadyForUpload(_))
654 .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
655 EXPECT_CALL(*mock_blacklist_store_, ClearBlacklist());
656
657 Blacklist(suggestions_service.get(), blacklisted_url);
658 suggestions_service->ClearBlacklist();
659
660 EXPECT_EQ(2, suggestions_data_callback_count_);
661 EXPECT_FALSE(blacklisting_failed_);
662 }
663
664 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfNotInBlacklist) {
665 UndoBlacklistURLFailsHelper(true);
666 }
667
668 TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfAlreadyCandidate) {
669 UndoBlacklistURLFailsHelper(false);
670 }
671
672 TEST_F(SuggestionsServiceTest, GetBlacklistedUrl) {
673 std::unique_ptr<GURL> request_url;
674 std::unique_ptr<net::FakeURLFetcher> fetcher;
675 GURL retrieved_url;
676
677 // Not a blacklist request.
678 request_url.reset(new GURL("http://not-blacklisting.com/a?b=c"));
679 fetcher = CreateURLFetcher(*request_url, nullptr, "", net::HTTP_OK,
680 net::URLRequestStatus::SUCCESS);
681 EXPECT_FALSE(SuggestionsService::GetBlacklistedUrl(*fetcher, &retrieved_url));
682
683 // An actual blacklist request.
684 std::string blacklisted_url = "http://blacklisted.com/a?b=c&d=e";
685 std::string encoded_blacklisted_url =
686 "http%3A%2F%2Fblacklisted.com%2Fa%3Fb%3Dc%26d%3De";
687 std::string blacklist_request_prefix(
688 SuggestionsService::BuildSuggestionsBlacklistURLPrefix());
689 request_url.reset(
690 new GURL(blacklist_request_prefix + encoded_blacklisted_url));
691 fetcher.reset();
692 fetcher = CreateURLFetcher(*request_url, nullptr, "", net::HTTP_OK,
693 net::URLRequestStatus::SUCCESS);
694 EXPECT_TRUE(SuggestionsService::GetBlacklistedUrl(*fetcher, &retrieved_url));
695 EXPECT_EQ(blacklisted_url, retrieved_url.spec());
696 }
697
698 TEST_F(SuggestionsServiceTest, UpdateBlacklistDelay) {
699 std::unique_ptr<SuggestionsService> suggestions_service(
700 CreateSuggestionsServiceWithMocks());
701 base::TimeDelta initial_delay = suggestions_service->blacklist_delay();
702
703 // Delay unchanged on success.
704 suggestions_service->UpdateBlacklistDelay(true);
705 EXPECT_EQ(initial_delay, suggestions_service->blacklist_delay());
706
707 // Delay increases on failure.
708 suggestions_service->UpdateBlacklistDelay(false);
709 EXPECT_GT(suggestions_service->blacklist_delay(), initial_delay);
710
711 // Delay resets on success.
712 suggestions_service->UpdateBlacklistDelay(true);
713 EXPECT_EQ(initial_delay, suggestions_service->blacklist_delay());
714 }
715
716 TEST_F(SuggestionsServiceTest, CheckDefaultTimeStamps) {
717 std::unique_ptr<SuggestionsService> suggestions_service(
718 CreateSuggestionsServiceWithMocks());
719 SuggestionsProfile suggestions =
720 CreateSuggestionsProfileWithExpiryTimestamps();
721 suggestions_service->SetDefaultExpiryTimestamp(&suggestions,
722 kTestDefaultExpiry);
723 EXPECT_EQ(kTestSetExpiry, suggestions.suggestions(0).expiry_ts());
724 EXPECT_EQ(kTestDefaultExpiry, suggestions.suggestions(1).expiry_ts());
725 }
726
727 TEST_F(SuggestionsServiceTest, GetPageThumbnail) {
728 std::unique_ptr<SuggestionsService> suggestions_service(
729 CreateSuggestionsServiceWithMocks());
730 ASSERT_TRUE(suggestions_service != nullptr);
731
732 GURL test_url(kTestUrl);
733 GURL thumbnail_url("https://www.thumbnails.com/thumb.jpg");
734 base::Callback<void(const GURL&, const gfx::Image&)> dummy_callback;
735
736 EXPECT_CALL(*mock_thumbnail_manager_, GetImageForURL(test_url, _));
737 suggestions_service->GetPageThumbnail(test_url, dummy_callback);
738
739 EXPECT_CALL(*mock_thumbnail_manager_, AddImageURL(test_url, thumbnail_url));
740 EXPECT_CALL(*mock_thumbnail_manager_, GetImageForURL(test_url, _));
741 suggestions_service->GetPageThumbnailWithURL(test_url, thumbnail_url,
742 dummy_callback);
743
744 }
745
746 } // namespace suggestions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698