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

Side by Side Diff: components/reading_list/ios/reading_list_model_unittest.mm

Issue 2764533002: Reading List iOS: Use external clock in ReadingListEntry. (Closed)
Patch Set: jitter Created 3 years, 9 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/reading_list/ios/reading_list_model.h"
6
7 #include "base/bind.h"
8 #include "base/memory/ptr_util.h"
9 #import "base/test/ios/wait_util.h"
10 #include "components/reading_list/ios/reading_list_model_impl.h"
11 #include "components/reading_list/ios/reading_list_model_storage.h"
12 #include "components/reading_list/ios/reading_list_store_delegate.h"
13 #include "components/sync/model/metadata_change_list.h"
14 #include "components/sync/model/model_error.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace {
18
19 const GURL callback_url("http://example.com");
20 const std::string callback_title("test title");
21
22 class TestReadingListStorageObserver {
23 public:
24 virtual void ReadingListDidSaveEntry() = 0;
25 virtual void ReadingListDidRemoveEntry() = 0;
26 };
27
28 class TestReadingListStorage : public ReadingListModelStorage {
29 public:
30 TestReadingListStorage(TestReadingListStorageObserver* observer)
31 : ReadingListModelStorage(
32 base::Bind(&syncer::ModelTypeChangeProcessor::Create,
33 base::RepeatingClosure()),
34 syncer::READING_LIST),
35 entries_(new ReadingListStoreDelegate::ReadingListEntries()),
36 observer_(observer) {}
37
38 void AddSampleEntries() {
39 // Adds timer and interlace read/unread entry creation to avoid having two
40 // entries with the same creation timestamp.
41 ReadingListEntry unread_a(GURL("http://unread_a.com"), "unread_a");
42 entries_->insert(
43 std::make_pair(GURL("http://unread_a.com"), std::move(unread_a)));
44 base::test::ios::SpinRunLoopWithMinDelay(
45 base::TimeDelta::FromMilliseconds(5));
46
47 ReadingListEntry read_a(GURL("http://read_a.com"), "read_a");
48 read_a.SetRead(true);
49 entries_->insert(
50 std::make_pair(GURL("http://read_a.com"), std::move(read_a)));
51 base::test::ios::SpinRunLoopWithMinDelay(
52 base::TimeDelta::FromMilliseconds(5));
53
54 ReadingListEntry unread_b(GURL("http://unread_b.com"), "unread_b");
55 entries_->insert(
56 std::make_pair(GURL("http://unread_b.com"), std::move(unread_b)));
57 base::test::ios::SpinRunLoopWithMinDelay(
58 base::TimeDelta::FromMilliseconds(5));
59
60 ReadingListEntry read_b(GURL("http://read_b.com"), "read_b");
61 read_b.SetRead(true);
62 entries_->insert(
63 std::make_pair(GURL("http://read_b.com"), std::move(read_b)));
64 base::test::ios::SpinRunLoopWithMinDelay(
65 base::TimeDelta::FromMilliseconds(5));
66
67 ReadingListEntry unread_c(GURL("http://unread_c.com"), "unread_c");
68 entries_->insert(
69 std::make_pair(GURL("http://unread_c.com"), std::move(unread_c)));
70 base::test::ios::SpinRunLoopWithMinDelay(
71 base::TimeDelta::FromMilliseconds(5));
72
73 ReadingListEntry read_c(GURL("http://read_c.com"), "read_c");
74 read_c.SetRead(true);
75 entries_->insert(
76 std::make_pair(GURL("http://read_c.com"), std::move(read_c)));
77 base::test::ios::SpinRunLoopWithMinDelay(
78 base::TimeDelta::FromMilliseconds(5));
79
80 ReadingListEntry unread_d(GURL("http://unread_d.com"), "unread_d");
81 entries_->insert(
82 std::make_pair(GURL("http://unread_d.com"), std::move(unread_d)));
83 base::test::ios::SpinRunLoopWithMinDelay(
84 base::TimeDelta::FromMilliseconds(5));
85 }
86
87 void SetReadingListModel(ReadingListModel* model,
88 ReadingListStoreDelegate* delegate) override {
89 delegate->StoreLoaded(std::move(entries_));
90 }
91
92 // Saves or updates an entry. If the entry is not yet in the database, it is
93 // created.
94 void SaveEntry(const ReadingListEntry& entry) override {
95 observer_->ReadingListDidSaveEntry();
96 }
97
98 // Removes an entry from the storage.
99 void RemoveEntry(const ReadingListEntry& entry) override {
100 observer_->ReadingListDidRemoveEntry();
101 }
102
103 std::unique_ptr<ScopedBatchUpdate> EnsureBatchCreated() override {
104 return std::unique_ptr<ScopedBatchUpdate>();
105 }
106
107 // Syncing is not used in this test class.
108 std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
109 override {
110 NOTREACHED();
111 return std::unique_ptr<syncer::MetadataChangeList>();
112 }
113
114 base::Optional<syncer::ModelError> MergeSyncData(
115 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
116 syncer::EntityDataMap entity_data_map) override {
117 NOTREACHED();
118 return {};
119 }
120
121 base::Optional<syncer::ModelError> ApplySyncChanges(
122 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
123 syncer::EntityChangeList entity_changes) override {
124 NOTREACHED();
125 return {};
126 }
127
128 void GetData(StorageKeyList storage_keys, DataCallback callback) override {
129 NOTREACHED();
130 return;
131 }
132
133 void GetAllData(DataCallback callback) override {
134 NOTREACHED();
135 return;
136 }
137
138 std::string GetClientTag(const syncer::EntityData& entity_data) override {
139 NOTREACHED();
140 return "";
141 }
142
143 std::string GetStorageKey(const syncer::EntityData& entity_data) override {
144 NOTREACHED();
145 return "";
146 }
147
148 private:
149 std::unique_ptr<ReadingListStoreDelegate::ReadingListEntries> entries_;
150 TestReadingListStorageObserver* observer_;
151 };
152
153 class ReadingListModelTest : public ReadingListModelObserver,
154 public TestReadingListStorageObserver,
155 public testing::Test {
156 public:
157 ReadingListModelTest()
158 : callback_called_(false), model_(new ReadingListModelImpl()) {
159 ClearCounts();
160 model_->AddObserver(this);
161 }
162 ~ReadingListModelTest() override {}
163
164 void SetStorage(std::unique_ptr<TestReadingListStorage> storage) {
165 model_ =
166 base::MakeUnique<ReadingListModelImpl>(std::move(storage), nullptr);
167 ClearCounts();
168 model_->AddObserver(this);
169 }
170
171 void ClearCounts() {
172 observer_loaded_ = observer_started_batch_update_ =
173 observer_completed_batch_update_ = observer_deleted_ =
174 observer_remove_ = observer_move_ = observer_add_ =
175 observer_did_add_ = observer_update_ = observer_did_apply_ =
176 storage_saved_ = storage_removed_ = 0;
177 }
178
179 void AssertObserverCount(int observer_loaded,
180 int observer_started_batch_update,
181 int observer_completed_batch_update,
182 int observer_deleted,
183 int observer_remove,
184 int observer_move,
185 int observer_add,
186 int observer_update,
187 int observer_did_apply) {
188 ASSERT_EQ(observer_loaded, observer_loaded_);
189 ASSERT_EQ(observer_started_batch_update, observer_started_batch_update_);
190 ASSERT_EQ(observer_completed_batch_update,
191 observer_completed_batch_update_);
192 ASSERT_EQ(observer_deleted, observer_deleted_);
193 ASSERT_EQ(observer_remove, observer_remove_);
194 ASSERT_EQ(observer_move, observer_move_);
195 // Add and did_add should be the same.
196 ASSERT_EQ(observer_add, observer_add_);
197 ASSERT_EQ(observer_add, observer_did_add_);
198 ASSERT_EQ(observer_update, observer_update_);
199 ASSERT_EQ(observer_did_apply, observer_did_apply_);
200 }
201
202 void AssertStorageCount(int storage_saved, int storage_removed) {
203 ASSERT_EQ(storage_saved, storage_saved_);
204 ASSERT_EQ(storage_removed, storage_removed_);
205 }
206
207 // ReadingListModelObserver
208 void ReadingListModelLoaded(const ReadingListModel* model) override {
209 observer_loaded_ += 1;
210 }
211 void ReadingListModelBeganBatchUpdates(
212 const ReadingListModel* model) override {
213 observer_started_batch_update_ += 1;
214 }
215 void ReadingListModelCompletedBatchUpdates(
216 const ReadingListModel* model) override {
217 observer_completed_batch_update_ += 1;
218 }
219 void ReadingListModelBeingDeleted(const ReadingListModel* model) override {
220 observer_deleted_ += 1;
221 }
222 void ReadingListWillRemoveEntry(const ReadingListModel* model,
223 const GURL& url) override {
224 observer_remove_ += 1;
225 }
226 void ReadingListWillMoveEntry(const ReadingListModel* model,
227 const GURL& url) override {
228 observer_move_ += 1;
229 }
230 void ReadingListWillAddEntry(const ReadingListModel* model,
231 const ReadingListEntry& entry) override {
232 observer_add_ += 1;
233 }
234 void ReadingListDidAddEntry(const ReadingListModel* model,
235 const GURL& url,
236 reading_list::EntrySource entry_source) override {
237 observer_did_add_ += 1;
238 }
239 void ReadingListWillUpdateEntry(const ReadingListModel* model,
240 const GURL& url) override {
241 observer_update_ += 1;
242 }
243 void ReadingListDidApplyChanges(ReadingListModel* model) override {
244 observer_did_apply_ += 1;
245 }
246
247 void ReadingListDidSaveEntry() override { storage_saved_ += 1; }
248 void ReadingListDidRemoveEntry() override { storage_removed_ += 1; }
249
250 size_t UnreadSize() {
251 size_t size = 0;
252 for (const auto& url : model_->Keys()) {
253 const ReadingListEntry* entry = model_->GetEntryByURL(url);
254 if (!entry->IsRead()) {
255 size++;
256 }
257 }
258 DCHECK_EQ(size, model_->unread_size());
259 return size;
260 }
261
262 size_t ReadSize() {
263 size_t size = 0;
264 for (const auto& url : model_->Keys()) {
265 const ReadingListEntry* entry = model_->GetEntryByURL(url);
266 if (entry->IsRead()) {
267 size++;
268 }
269 }
270 return size;
271 }
272
273 void Callback(const ReadingListEntry& entry) {
274 EXPECT_EQ(callback_url, entry.URL());
275 EXPECT_EQ(callback_title, entry.Title());
276 callback_called_ = true;
277 }
278
279 bool CallbackCalled() { return callback_called_; }
280
281 protected:
282 int observer_loaded_;
283 int observer_started_batch_update_;
284 int observer_completed_batch_update_;
285 int observer_deleted_;
286 int observer_remove_;
287 int observer_move_;
288 int observer_add_;
289 int observer_did_add_;
290 int observer_update_;
291 int observer_did_apply_;
292 int storage_saved_;
293 int storage_removed_;
294 bool callback_called_;
295
296 std::unique_ptr<ReadingListModelImpl> model_;
297 };
298
299 // Tests creating an empty model.
300 TEST_F(ReadingListModelTest, EmptyLoaded) {
301 EXPECT_TRUE(model_->loaded());
302 AssertObserverCount(1, 0, 0, 0, 0, 0, 0, 0, 0);
303 EXPECT_EQ(0ul, UnreadSize());
304 EXPECT_EQ(0ul, ReadSize());
305 model_->Shutdown();
306 EXPECT_FALSE(model_->loaded());
307 AssertObserverCount(1, 0, 0, 1, 0, 0, 0, 0, 0);
308 }
309
310 // Tests load model.
311 TEST_F(ReadingListModelTest, ModelLoaded) {
312 ClearCounts();
313 auto storage = base::MakeUnique<TestReadingListStorage>(this);
314 storage->AddSampleEntries();
315 SetStorage(std::move(storage));
316
317 AssertObserverCount(1, 0, 0, 0, 0, 0, 0, 0, 0);
318 std::map<GURL, std::string> loaded_entries;
319 int size = 0;
320 for (const auto& url : model_->Keys()) {
321 size++;
322 const ReadingListEntry* entry = model_->GetEntryByURL(url);
323 loaded_entries[url] = entry->Title();
324 }
325 EXPECT_EQ(size, 7);
326 EXPECT_EQ(loaded_entries[GURL("http://unread_a.com")], "unread_a");
327 EXPECT_EQ(loaded_entries[GURL("http://unread_b.com")], "unread_b");
328 EXPECT_EQ(loaded_entries[GURL("http://unread_c.com")], "unread_c");
329 EXPECT_EQ(loaded_entries[GURL("http://unread_d.com")], "unread_d");
330 EXPECT_EQ(loaded_entries[GURL("http://read_a.com")], "read_a");
331 EXPECT_EQ(loaded_entries[GURL("http://read_b.com")], "read_b");
332 EXPECT_EQ(loaded_entries[GURL("http://read_c.com")], "read_c");
333 }
334
335 // Tests adding entry.
336 TEST_F(ReadingListModelTest, AddEntry) {
337 auto storage = base::MakeUnique<TestReadingListStorage>(this);
338 SetStorage(std::move(storage));
339 ClearCounts();
340
341 const ReadingListEntry& entry =
342 model_->AddEntry(GURL("http://example.com"), "\n \tsample Test ",
343 reading_list::ADDED_VIA_CURRENT_APP);
344 EXPECT_EQ(GURL("http://example.com"), entry.URL());
345 EXPECT_EQ("sample Test", entry.Title());
346
347 AssertObserverCount(0, 0, 0, 0, 0, 0, 1, 0, 1);
348 AssertStorageCount(1, 0);
349 EXPECT_EQ(1ul, UnreadSize());
350 EXPECT_EQ(0ul, ReadSize());
351 EXPECT_TRUE(model_->GetLocalUnseenFlag());
352
353 const ReadingListEntry* other_entry =
354 model_->GetEntryByURL(GURL("http://example.com"));
355 EXPECT_NE(other_entry, nullptr);
356 EXPECT_FALSE(other_entry->IsRead());
357 EXPECT_EQ(GURL("http://example.com"), other_entry->URL());
358 EXPECT_EQ("sample Test", other_entry->Title());
359 }
360
361 // Tests addin entry from sync.
362 TEST_F(ReadingListModelTest, SyncAddEntry) {
363 auto storage = base::MakeUnique<TestReadingListStorage>(this);
364 SetStorage(std::move(storage));
365 auto entry =
366 base::MakeUnique<ReadingListEntry>(GURL("http://example.com"), "sample");
367 entry->SetRead(true);
368 ClearCounts();
369
370 model_->SyncAddEntry(std::move(entry));
371 AssertObserverCount(0, 0, 0, 0, 0, 0, 1, 0, 1);
372 AssertStorageCount(0, 0);
373 EXPECT_EQ(0ul, UnreadSize());
374 EXPECT_EQ(1ul, ReadSize());
375 ClearCounts();
376 }
377
378 // Tests updating entry from sync.
379 TEST_F(ReadingListModelTest, SyncMergeEntry) {
380 auto storage = base::MakeUnique<TestReadingListStorage>(this);
381 SetStorage(std::move(storage));
382 model_->AddEntry(GURL("http://example.com"), "sample",
383 reading_list::ADDED_VIA_CURRENT_APP);
384 const base::FilePath distilled_path("distilled/page.html");
385 const GURL distilled_url("http://example.com/distilled");
386 int64_t size = 50;
387 int64_t time = 100;
388 model_->SetEntryDistilledInfo(GURL("http://example.com"), distilled_path,
389 distilled_url, size, time);
390 const ReadingListEntry* local_entry =
391 model_->GetEntryByURL(GURL("http://example.com"));
392 int64_t local_update_time = local_entry->UpdateTime();
393
394 base::test::ios::SpinRunLoopWithMinDelay(
395 base::TimeDelta::FromMilliseconds(10));
396 auto sync_entry =
397 base::MakeUnique<ReadingListEntry>(GURL("http://example.com"), "sample");
398 sync_entry->SetRead(true);
399 ASSERT_GT(sync_entry->UpdateTime(), local_update_time);
400 int64_t sync_update_time = sync_entry->UpdateTime();
401 EXPECT_TRUE(sync_entry->DistilledPath().empty());
402
403 EXPECT_EQ(1ul, UnreadSize());
404 EXPECT_EQ(0ul, ReadSize());
405
406 ReadingListEntry* merged_entry =
407 model_->SyncMergeEntry(std::move(sync_entry));
408 EXPECT_EQ(0ul, UnreadSize());
409 EXPECT_EQ(1ul, ReadSize());
410 EXPECT_EQ(merged_entry->DistilledPath(),
411 base::FilePath("distilled/page.html"));
412 EXPECT_EQ(merged_entry->UpdateTime(), sync_update_time);
413 EXPECT_EQ(size, merged_entry->DistillationSize());
414 EXPECT_EQ(time, merged_entry->DistillationTime());
415 }
416
417 // Tests deleting entry.
418 TEST_F(ReadingListModelTest, RemoveEntryByUrl) {
419 auto storage = base::MakeUnique<TestReadingListStorage>(this);
420 SetStorage(std::move(storage));
421 model_->AddEntry(GURL("http://example.com"), "sample",
422 reading_list::ADDED_VIA_CURRENT_APP);
423 ClearCounts();
424 EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
425 EXPECT_EQ(1ul, UnreadSize());
426 EXPECT_EQ(0ul, ReadSize());
427 model_->RemoveEntryByURL(GURL("http://example.com"));
428 AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 1);
429 AssertStorageCount(0, 1);
430 EXPECT_EQ(0ul, UnreadSize());
431 EXPECT_EQ(0ul, ReadSize());
432 EXPECT_EQ(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
433
434 model_->AddEntry(GURL("http://example.com"), "sample",
435 reading_list::ADDED_VIA_CURRENT_APP);
436 model_->SetReadStatus(GURL("http://example.com"), true);
437 ClearCounts();
438 EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
439 EXPECT_EQ(0ul, UnreadSize());
440 EXPECT_EQ(1ul, ReadSize());
441 model_->RemoveEntryByURL(GURL("http://example.com"));
442 AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 1);
443 AssertStorageCount(0, 1);
444 EXPECT_EQ(0ul, UnreadSize());
445 EXPECT_EQ(0ul, ReadSize());
446 EXPECT_EQ(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
447 }
448
449 // Tests deleting entry from sync.
450 TEST_F(ReadingListModelTest, RemoveSyncEntryByUrl) {
451 auto storage = base::MakeUnique<TestReadingListStorage>(this);
452 SetStorage(std::move(storage));
453 model_->AddEntry(GURL("http://example.com"), "sample",
454 reading_list::ADDED_VIA_CURRENT_APP);
455 ClearCounts();
456 EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
457 EXPECT_EQ(1ul, UnreadSize());
458 EXPECT_EQ(0ul, ReadSize());
459 model_->SyncRemoveEntry(GURL("http://example.com"));
460 AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 1);
461 AssertStorageCount(0, 0);
462 EXPECT_EQ(0ul, UnreadSize());
463 EXPECT_EQ(0ul, ReadSize());
464 EXPECT_EQ(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
465
466 model_->AddEntry(GURL("http://example.com"), "sample",
467 reading_list::ADDED_VIA_CURRENT_APP);
468 model_->SetReadStatus(GURL("http://example.com"), true);
469 ClearCounts();
470 EXPECT_NE(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
471 EXPECT_EQ(0ul, UnreadSize());
472 EXPECT_EQ(1ul, ReadSize());
473 model_->SyncRemoveEntry(GURL("http://example.com"));
474 AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 1);
475 AssertStorageCount(0, 0);
476 EXPECT_EQ(0ul, UnreadSize());
477 EXPECT_EQ(0ul, ReadSize());
478 EXPECT_EQ(model_->GetEntryByURL(GURL("http://example.com")), nullptr);
479 }
480
481 // Tests marking entry read.
482 TEST_F(ReadingListModelTest, ReadEntry) {
483 model_->AddEntry(GURL("http://example.com"), "sample",
484 reading_list::ADDED_VIA_CURRENT_APP);
485
486 ClearCounts();
487 model_->SetReadStatus(GURL("http://example.com"), true);
488 AssertObserverCount(0, 0, 0, 0, 0, 1, 0, 0, 1);
489 EXPECT_EQ(0ul, UnreadSize());
490 EXPECT_EQ(1ul, ReadSize());
491 EXPECT_EQ(0ul, model_->unseen_size());
492
493 const ReadingListEntry* other_entry =
494 model_->GetEntryByURL(GURL("http://example.com"));
495 EXPECT_NE(other_entry, nullptr);
496 EXPECT_TRUE(other_entry->IsRead());
497 EXPECT_EQ(GURL("http://example.com"), other_entry->URL());
498 EXPECT_EQ("sample", other_entry->Title());
499 }
500
501 // Tests accessing existing entry.
502 TEST_F(ReadingListModelTest, EntryFromURL) {
503 GURL url1("http://example.com");
504 GURL url2("http://example2.com");
505 std::string entry1_title = "foo bar qux";
506 model_->AddEntry(url1, entry1_title, reading_list::ADDED_VIA_CURRENT_APP);
507
508 // Check call with nullptr |read| parameter.
509 const ReadingListEntry* entry1 = model_->GetEntryByURL(url1);
510 EXPECT_NE(nullptr, entry1);
511 EXPECT_EQ(entry1_title, entry1->Title());
512
513 entry1 = model_->GetEntryByURL(url1);
514 EXPECT_NE(nullptr, entry1);
515 EXPECT_EQ(entry1_title, entry1->Title());
516 EXPECT_EQ(entry1->IsRead(), false);
517 model_->SetReadStatus(url1, true);
518 entry1 = model_->GetEntryByURL(url1);
519 EXPECT_NE(nullptr, entry1);
520 EXPECT_EQ(entry1_title, entry1->Title());
521 EXPECT_EQ(entry1->IsRead(), true);
522
523 const ReadingListEntry* entry2 = model_->GetEntryByURL(url2);
524 EXPECT_EQ(nullptr, entry2);
525 }
526
527 // Tests mark entry unread.
528 TEST_F(ReadingListModelTest, UnreadEntry) {
529 // Setup.
530 model_->AddEntry(GURL("http://example.com"), "sample",
531 reading_list::ADDED_VIA_CURRENT_APP);
532 EXPECT_TRUE(model_->GetLocalUnseenFlag());
533 model_->SetReadStatus(GURL("http://example.com"), true);
534 ClearCounts();
535 EXPECT_EQ(0ul, UnreadSize());
536 EXPECT_EQ(1ul, ReadSize());
537 EXPECT_FALSE(model_->GetLocalUnseenFlag());
538
539 // Action.
540 model_->SetReadStatus(GURL("http://example.com"), false);
541
542 // Tests.
543 AssertObserverCount(0, 0, 0, 0, 0, 1, 0, 0, 1);
544 EXPECT_EQ(1ul, UnreadSize());
545 EXPECT_EQ(0ul, ReadSize());
546 EXPECT_FALSE(model_->GetLocalUnseenFlag());
547
548 const ReadingListEntry* other_entry =
549 model_->GetEntryByURL(GURL("http://example.com"));
550 EXPECT_NE(other_entry, nullptr);
551 EXPECT_FALSE(other_entry->IsRead());
552 EXPECT_EQ(GURL("http://example.com"), other_entry->URL());
553 EXPECT_EQ("sample", other_entry->Title());
554 }
555
556 // Tests batch updates observers are called.
557 TEST_F(ReadingListModelTest, BatchUpdates) {
558 auto token = model_->BeginBatchUpdates();
559 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0);
560 EXPECT_TRUE(model_->IsPerformingBatchUpdates());
561
562 delete token.release();
563 AssertObserverCount(1, 1, 1, 0, 0, 0, 0, 0, 0);
564 EXPECT_FALSE(model_->IsPerformingBatchUpdates());
565 }
566
567 // Tests batch updates are reentrant.
568 TEST_F(ReadingListModelTest, BatchUpdatesReentrant) {
569 // When two updates happen at the same time, the notification is only sent
570 // for beginning of first update and completion of last update.
571 EXPECT_FALSE(model_->IsPerformingBatchUpdates());
572
573 auto token = model_->BeginBatchUpdates();
574 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0);
575 EXPECT_TRUE(model_->IsPerformingBatchUpdates());
576
577 auto second_token = model_->BeginBatchUpdates();
578 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0);
579 EXPECT_TRUE(model_->IsPerformingBatchUpdates());
580
581 delete token.release();
582 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0);
583 EXPECT_TRUE(model_->IsPerformingBatchUpdates());
584
585 delete second_token.release();
586 AssertObserverCount(1, 1, 1, 0, 0, 0, 0, 0, 0);
587 EXPECT_FALSE(model_->IsPerformingBatchUpdates());
588
589 // Consequent updates send notifications.
590 auto third_token = model_->BeginBatchUpdates();
591 AssertObserverCount(1, 2, 1, 0, 0, 0, 0, 0, 0);
592 EXPECT_TRUE(model_->IsPerformingBatchUpdates());
593
594 delete third_token.release();
595 AssertObserverCount(1, 2, 2, 0, 0, 0, 0, 0, 0);
596 EXPECT_FALSE(model_->IsPerformingBatchUpdates());
597 }
598
599 // Tests setting title on unread entry.
600 TEST_F(ReadingListModelTest, UpdateEntryTitle) {
601 const GURL gurl("http://example.com");
602 const ReadingListEntry& entry =
603 model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
604 ClearCounts();
605
606 model_->SetEntryTitle(gurl, "ping");
607 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1);
608 EXPECT_EQ("ping", entry.Title());
609 }
610 // Tests setting distillation state on unread entry.
611 TEST_F(ReadingListModelTest, UpdateEntryDistilledState) {
612 const GURL gurl("http://example.com");
613 const ReadingListEntry& entry =
614 model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
615 ClearCounts();
616
617 model_->SetEntryDistilledState(gurl, ReadingListEntry::PROCESSING);
618 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1);
619 EXPECT_EQ(ReadingListEntry::PROCESSING, entry.DistilledState());
620 }
621
622 // Tests setting distillation info on unread entry.
623 TEST_F(ReadingListModelTest, UpdateDistilledInfo) {
624 const GURL gurl("http://example.com");
625 const ReadingListEntry& entry =
626 model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
627 ClearCounts();
628
629 const base::FilePath distilled_path("distilled/page.html");
630 const GURL distilled_url("http://example.com/distilled");
631 int64_t size = 50;
632 int64_t time = 100;
633 model_->SetEntryDistilledInfo(GURL("http://example.com"), distilled_path,
634 distilled_url, size, time);
635 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1);
636 EXPECT_EQ(ReadingListEntry::PROCESSED, entry.DistilledState());
637 EXPECT_EQ(distilled_path, entry.DistilledPath());
638 EXPECT_EQ(distilled_url, entry.DistilledURL());
639 EXPECT_EQ(size, entry.DistillationSize());
640 EXPECT_EQ(time, entry.DistillationTime());
641 }
642
643 // Tests setting title on read entry.
644 TEST_F(ReadingListModelTest, UpdateReadEntryTitle) {
645 const GURL gurl("http://example.com");
646 model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
647 model_->SetReadStatus(gurl, true);
648 const ReadingListEntry* entry = model_->GetEntryByURL(gurl);
649 ClearCounts();
650
651 model_->SetEntryTitle(gurl, "ping");
652 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1);
653 EXPECT_EQ("ping", entry->Title());
654 }
655
656 // Tests setting distillation state on read entry.
657 TEST_F(ReadingListModelTest, UpdateReadEntryState) {
658 const GURL gurl("http://example.com");
659 model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
660 model_->SetReadStatus(gurl, true);
661 const ReadingListEntry* entry = model_->GetEntryByURL(gurl);
662 ClearCounts();
663
664 model_->SetEntryDistilledState(gurl, ReadingListEntry::PROCESSING);
665 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1);
666 EXPECT_EQ(ReadingListEntry::PROCESSING, entry->DistilledState());
667 }
668
669 // Tests setting distillation info on read entry.
670 TEST_F(ReadingListModelTest, UpdateReadDistilledInfo) {
671 const GURL gurl("http://example.com");
672 model_->AddEntry(gurl, "sample", reading_list::ADDED_VIA_CURRENT_APP);
673 model_->SetReadStatus(gurl, true);
674 const ReadingListEntry* entry = model_->GetEntryByURL(gurl);
675 ClearCounts();
676
677 const base::FilePath distilled_path("distilled/page.html");
678 const GURL distilled_url("http://example.com/distilled");
679 int64_t size = 50;
680 int64_t time = 100;
681 model_->SetEntryDistilledInfo(GURL("http://example.com"), distilled_path,
682 distilled_url, size, time);
683 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1);
684 EXPECT_EQ(ReadingListEntry::PROCESSED, entry->DistilledState());
685 EXPECT_EQ(distilled_path, entry->DistilledPath());
686 EXPECT_EQ(distilled_url, entry->DistilledURL());
687 EXPECT_EQ(size, entry->DistillationSize());
688 EXPECT_EQ(time, entry->DistillationTime());
689 }
690
691 // Tests that ReadingListModel calls CallbackModelBeingDeleted when destroyed.
692 TEST_F(ReadingListModelTest, CallbackModelBeingDeleted) {
693 AssertObserverCount(1, 0, 0, 0, 0, 0, 0, 0, 0);
694 model_.reset();
695 AssertObserverCount(1, 0, 0, 1, 0, 0, 0, 0, 0);
696 }
697
698 // Tests that new line characters and spaces are collapsed in title.
699 TEST_F(ReadingListModelTest, TestTrimmingTitle) {
700 const GURL gurl("http://example.com");
701 std::string title = "\n This\ttitle \n contains new line \n characters ";
702 model_->AddEntry(gurl, title, reading_list::ADDED_VIA_CURRENT_APP);
703 model_->SetReadStatus(gurl, true);
704 const ReadingListEntry* entry = model_->GetEntryByURL(gurl);
705 EXPECT_EQ(entry->Title(), "This title contains new line characters");
706 model_->SetEntryTitle(gurl, "test");
707 EXPECT_EQ(entry->Title(), "test");
708 model_->SetEntryTitle(gurl, title);
709 EXPECT_EQ(entry->Title(), "This title contains new line characters");
710 }
711
712 } // namespace
OLDNEW
« no previous file with comments | « components/reading_list/ios/reading_list_model_unittest.cc ('k') | components/reading_list/ios/reading_list_store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698