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

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

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

Powered by Google App Engine
This is Rietveld 408576698