OLD | NEW |
| (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 "base/bind.h" | |
6 #include "base/memory/ptr_util.h" | |
7 #import "base/test/ios/wait_util.h" | |
8 #include "components/reading_list/reading_list_model_impl.h" | |
9 #include "components/reading_list/reading_list_model_storage.h" | |
10 #include "testing/gtest/include/gtest/gtest.h" | |
11 | |
12 namespace { | |
13 | |
14 const GURL callback_url("http://example.com"); | |
15 const std::string callback_title("test title"); | |
16 | |
17 class TestReadingListStorageObserver { | |
18 public: | |
19 virtual void ReadingListDidSaveEntry() = 0; | |
20 virtual void ReadingListDidRemoveEntry() = 0; | |
21 }; | |
22 | |
23 class TestReadingListStorage : public ReadingListModelStorage { | |
24 public: | |
25 TestReadingListStorage(TestReadingListStorageObserver* observer) | |
26 : read_(new std::vector<ReadingListEntry>()), | |
27 unread_(new std::vector<ReadingListEntry>()), | |
28 observer_(observer) {} | |
29 | |
30 void AddSampleEntries() { | |
31 // Adds timer and interlace read/unread entry creation to avoid having two | |
32 // entries with the same creation timestamp. | |
33 ReadingListEntry unread_a(GURL("http://unread_a.com"), "unread_a"); | |
34 base::test::ios::SpinRunLoopWithMinDelay( | |
35 base::TimeDelta::FromMilliseconds(5)); | |
36 ReadingListEntry read_a(GURL("http://read_a.com"), "read_a"); | |
37 base::test::ios::SpinRunLoopWithMinDelay( | |
38 base::TimeDelta::FromMilliseconds(5)); | |
39 ReadingListEntry unread_b(GURL("http://unread_b.com"), "unread_b"); | |
40 base::test::ios::SpinRunLoopWithMinDelay( | |
41 base::TimeDelta::FromMilliseconds(5)); | |
42 ReadingListEntry read_b(GURL("http://read_b.com"), "read_b"); | |
43 base::test::ios::SpinRunLoopWithMinDelay( | |
44 base::TimeDelta::FromMilliseconds(5)); | |
45 ReadingListEntry unread_c(GURL("http://unread_c.com"), "unread_c"); | |
46 base::test::ios::SpinRunLoopWithMinDelay( | |
47 base::TimeDelta::FromMilliseconds(5)); | |
48 ReadingListEntry read_c(GURL("http://read_c.com"), "read_c"); | |
49 base::test::ios::SpinRunLoopWithMinDelay( | |
50 base::TimeDelta::FromMilliseconds(5)); | |
51 ReadingListEntry unread_d(GURL("http://unread_d.com"), "unread_d"); | |
52 base::test::ios::SpinRunLoopWithMinDelay( | |
53 base::TimeDelta::FromMilliseconds(5)); | |
54 read_->push_back(std::move(read_c)); | |
55 read_->push_back(std::move(read_a)); | |
56 read_->push_back(std::move(read_b)); | |
57 | |
58 unread_->push_back(std::move(unread_a)); | |
59 unread_->push_back(std::move(unread_d)); | |
60 unread_->push_back(std::move(unread_c)); | |
61 unread_->push_back(std::move(unread_b)); | |
62 } | |
63 | |
64 void SetReadingListModel(ReadingListModel* model, | |
65 ReadingListStoreDelegate* delegate_) override { | |
66 delegate_->StoreLoaded(std::move(unread_), std::move(read_)); | |
67 } | |
68 | |
69 syncer::ModelTypeSyncBridge* GetModelTypeSyncBridge() override { | |
70 return nullptr; | |
71 } | |
72 | |
73 std::unique_ptr<ScopedBatchUpdate> EnsureBatchCreated() override { | |
74 return std::unique_ptr<ScopedBatchUpdate>(); | |
75 } | |
76 | |
77 // Saves or updates an entry. If the entry is not yet in the database, it is | |
78 // created. | |
79 void SaveEntry(const ReadingListEntry& entry, bool read) override { | |
80 observer_->ReadingListDidSaveEntry(); | |
81 } | |
82 | |
83 // Removed an entry from the storage. | |
84 void RemoveEntry(const ReadingListEntry& entry) override { | |
85 observer_->ReadingListDidRemoveEntry(); | |
86 } | |
87 | |
88 private: | |
89 std::unique_ptr<std::vector<ReadingListEntry>> read_; | |
90 std::unique_ptr<std::vector<ReadingListEntry>> unread_; | |
91 TestReadingListStorageObserver* observer_; | |
92 }; | |
93 | |
94 class ReadingListModelTest : public ReadingListModelObserver, | |
95 public TestReadingListStorageObserver, | |
96 public testing::Test { | |
97 public: | |
98 ReadingListModelTest() | |
99 : callback_called_(false), model_(new ReadingListModelImpl()) { | |
100 ClearCounts(); | |
101 model_->AddObserver(this); | |
102 } | |
103 ~ReadingListModelTest() override {} | |
104 | |
105 void SetStorage(std::unique_ptr<TestReadingListStorage> storage) { | |
106 model_ = | |
107 base::MakeUnique<ReadingListModelImpl>(std::move(storage), nullptr); | |
108 ClearCounts(); | |
109 model_->AddObserver(this); | |
110 } | |
111 | |
112 void ClearCounts() { | |
113 observer_loaded_ = observer_started_batch_update_ = | |
114 observer_completed_batch_update_ = observer_deleted_ = | |
115 observer_remove_unread_ = observer_remove_read_ = observer_move_ = | |
116 observer_add_unread_ = observer_add_read_ = | |
117 observer_update_unread_ = observer_update_read_ = | |
118 observer_did_apply_ = storage_saved_ = | |
119 storage_removed_ = 0; | |
120 } | |
121 | |
122 void AssertObserverCount(int observer_loaded, | |
123 int observer_started_batch_update, | |
124 int observer_completed_batch_update, | |
125 int observer_deleted, | |
126 int observer_remove_unread, | |
127 int observer_remove_read, | |
128 int observer_move, | |
129 int observer_add_unread, | |
130 int observer_add_read, | |
131 int observer_update_unread, | |
132 int observer_update_read, | |
133 int observer_did_apply) { | |
134 ASSERT_EQ(observer_loaded, observer_loaded_); | |
135 ASSERT_EQ(observer_started_batch_update, observer_started_batch_update_); | |
136 ASSERT_EQ(observer_completed_batch_update, | |
137 observer_completed_batch_update_); | |
138 ASSERT_EQ(observer_deleted, observer_deleted_); | |
139 ASSERT_EQ(observer_remove_unread, observer_remove_unread_); | |
140 ASSERT_EQ(observer_remove_read, observer_remove_read_); | |
141 ASSERT_EQ(observer_move, observer_move_); | |
142 ASSERT_EQ(observer_add_unread, observer_add_unread_); | |
143 ASSERT_EQ(observer_add_read, observer_add_read_); | |
144 ASSERT_EQ(observer_update_unread, observer_update_unread_); | |
145 ASSERT_EQ(observer_update_read, observer_update_read_); | |
146 ASSERT_EQ(observer_did_apply, observer_did_apply_); | |
147 } | |
148 | |
149 void AssertStorageCount(int storage_saved, int storage_removed) { | |
150 ASSERT_EQ(storage_saved, storage_saved_); | |
151 ASSERT_EQ(storage_removed, storage_removed_); | |
152 } | |
153 | |
154 // ReadingListModelObserver | |
155 void ReadingListModelLoaded(const ReadingListModel* model) override { | |
156 observer_loaded_ += 1; | |
157 } | |
158 void ReadingListModelBeganBatchUpdates( | |
159 const ReadingListModel* model) override { | |
160 observer_started_batch_update_ += 1; | |
161 } | |
162 void ReadingListModelCompletedBatchUpdates( | |
163 const ReadingListModel* model) override { | |
164 observer_completed_batch_update_ += 1; | |
165 } | |
166 void ReadingListModelBeingDeleted(const ReadingListModel* model) override { | |
167 observer_deleted_ += 1; | |
168 } | |
169 void ReadingListWillRemoveUnreadEntry(const ReadingListModel* model, | |
170 size_t index) override { | |
171 observer_remove_unread_ += 1; | |
172 } | |
173 void ReadingListWillMoveEntry(const ReadingListModel* model, | |
174 size_t index, | |
175 bool read) override { | |
176 observer_move_ += 1; | |
177 } | |
178 void ReadingListWillRemoveReadEntry(const ReadingListModel* model, | |
179 size_t index) override { | |
180 observer_remove_read_ += 1; | |
181 } | |
182 void ReadingListWillAddUnreadEntry(const ReadingListModel* model, | |
183 const ReadingListEntry& entry) override { | |
184 observer_add_unread_ += 1; | |
185 } | |
186 void ReadingListWillAddReadEntry(const ReadingListModel* model, | |
187 const ReadingListEntry& entry) override { | |
188 observer_add_read_ += 1; | |
189 } | |
190 void ReadingListWillUpdateUnreadEntry(const ReadingListModel* model, | |
191 size_t index) override { | |
192 observer_update_unread_ += 1; | |
193 } | |
194 void ReadingListWillUpdateReadEntry(const ReadingListModel* model, | |
195 size_t index) override { | |
196 observer_update_read_ += 1; | |
197 } | |
198 void ReadingListDidApplyChanges(ReadingListModel* model) override { | |
199 observer_did_apply_ += 1; | |
200 } | |
201 | |
202 void ReadingListDidSaveEntry() override { storage_saved_ += 1; } | |
203 void ReadingListDidRemoveEntry() override { storage_removed_ += 1; } | |
204 | |
205 void Callback(const ReadingListEntry& entry) { | |
206 EXPECT_EQ(callback_url, entry.URL()); | |
207 EXPECT_EQ(callback_title, entry.Title()); | |
208 callback_called_ = true; | |
209 } | |
210 | |
211 bool CallbackCalled() { return callback_called_; } | |
212 | |
213 protected: | |
214 int observer_loaded_; | |
215 int observer_started_batch_update_; | |
216 int observer_completed_batch_update_; | |
217 int observer_deleted_; | |
218 int observer_remove_unread_; | |
219 int observer_remove_read_; | |
220 int observer_move_; | |
221 int observer_add_unread_; | |
222 int observer_add_read_; | |
223 int observer_update_unread_; | |
224 int observer_update_read_; | |
225 int observer_did_apply_; | |
226 int storage_saved_; | |
227 int storage_removed_; | |
228 bool callback_called_; | |
229 | |
230 std::unique_ptr<ReadingListModelImpl> model_; | |
231 }; | |
232 | |
233 TEST_F(ReadingListModelTest, EmptyLoaded) { | |
234 EXPECT_TRUE(model_->loaded()); | |
235 AssertObserverCount(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
236 EXPECT_EQ(0ul, model_->unread_size()); | |
237 EXPECT_EQ(0ul, model_->read_size()); | |
238 model_->Shutdown(); | |
239 EXPECT_FALSE(model_->loaded()); | |
240 AssertObserverCount(1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); | |
241 } | |
242 | |
243 TEST_F(ReadingListModelTest, ModelLoaded) { | |
244 ClearCounts(); | |
245 auto storage = base::MakeUnique<TestReadingListStorage>(this); | |
246 storage->AddSampleEntries(); | |
247 SetStorage(std::move(storage)); | |
248 | |
249 AssertObserverCount(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
250 EXPECT_EQ(model_->read_size(), 3u); | |
251 EXPECT_EQ(model_->GetReadEntryAtIndex(0).Title(), "read_c"); | |
252 EXPECT_EQ(model_->GetReadEntryAtIndex(1).Title(), "read_b"); | |
253 EXPECT_EQ(model_->GetReadEntryAtIndex(2).Title(), "read_a"); | |
254 | |
255 EXPECT_EQ(model_->unread_size(), 4u); | |
256 EXPECT_EQ(model_->GetUnreadEntryAtIndex(0).Title(), "unread_d"); | |
257 EXPECT_EQ(model_->GetUnreadEntryAtIndex(1).Title(), "unread_c"); | |
258 EXPECT_EQ(model_->GetUnreadEntryAtIndex(2).Title(), "unread_b"); | |
259 EXPECT_EQ(model_->GetUnreadEntryAtIndex(3).Title(), "unread_a"); | |
260 } | |
261 | |
262 TEST_F(ReadingListModelTest, AddEntry) { | |
263 auto storage = base::MakeUnique<TestReadingListStorage>(this); | |
264 SetStorage(std::move(storage)); | |
265 ClearCounts(); | |
266 | |
267 const ReadingListEntry& entry = | |
268 model_->AddEntry(GURL("http://example.com"), "\n \tsample Test "); | |
269 EXPECT_EQ(GURL("http://example.com"), entry.URL()); | |
270 EXPECT_EQ("sample Test", entry.Title()); | |
271 | |
272 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1); | |
273 AssertStorageCount(1, 0); | |
274 EXPECT_EQ(1ul, model_->unread_size()); | |
275 EXPECT_EQ(0ul, model_->read_size()); | |
276 EXPECT_TRUE(model_->HasUnseenEntries()); | |
277 | |
278 const ReadingListEntry& other_entry = model_->GetUnreadEntryAtIndex(0); | |
279 EXPECT_EQ(GURL("http://example.com"), other_entry.URL()); | |
280 EXPECT_EQ("sample Test", other_entry.Title()); | |
281 } | |
282 | |
283 TEST_F(ReadingListModelTest, SyncAddEntry) { | |
284 auto storage = base::MakeUnique<TestReadingListStorage>(this); | |
285 SetStorage(std::move(storage)); | |
286 auto entry = | |
287 base::MakeUnique<ReadingListEntry>(GURL("http://example.com"), "sample"); | |
288 ClearCounts(); | |
289 | |
290 model_->SyncAddEntry(std::move(entry), true); | |
291 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1); | |
292 AssertStorageCount(0, 0); | |
293 ASSERT_EQ(model_->unread_size(), 0u); | |
294 ASSERT_EQ(model_->read_size(), 1u); | |
295 ClearCounts(); | |
296 } | |
297 | |
298 TEST_F(ReadingListModelTest, SyncMergeEntry) { | |
299 auto storage = base::MakeUnique<TestReadingListStorage>(this); | |
300 SetStorage(std::move(storage)); | |
301 model_->AddEntry(GURL("http://example.com"), "sample"); | |
302 model_->SetEntryDistilledPath(GURL("http://example.com"), | |
303 base::FilePath("distilled/page.html")); | |
304 const ReadingListEntry* local_entry = | |
305 model_->GetEntryFromURL(GURL("http://example.com"), nullptr); | |
306 int64_t local_update_time = local_entry->UpdateTime(); | |
307 | |
308 base::test::ios::SpinRunLoopWithMinDelay( | |
309 base::TimeDelta::FromMilliseconds(10)); | |
310 auto sync_entry = | |
311 base::MakeUnique<ReadingListEntry>(GURL("http://example.com"), "sample"); | |
312 ASSERT_GT(sync_entry->UpdateTime(), local_update_time); | |
313 int64_t sync_update_time = sync_entry->UpdateTime(); | |
314 EXPECT_TRUE(sync_entry->DistilledPath().empty()); | |
315 | |
316 EXPECT_EQ(model_->unread_size(), 1u); | |
317 EXPECT_EQ(model_->read_size(), 0u); | |
318 | |
319 ReadingListEntry* merged_entry = | |
320 model_->SyncMergeEntry(std::move(sync_entry), true); | |
321 EXPECT_EQ(model_->unread_size(), 0u); | |
322 EXPECT_EQ(model_->read_size(), 1u); | |
323 EXPECT_EQ(merged_entry->DistilledPath(), | |
324 base::FilePath("distilled/page.html")); | |
325 EXPECT_EQ(merged_entry->UpdateTime(), sync_update_time); | |
326 } | |
327 | |
328 TEST_F(ReadingListModelTest, RemoveEntryByUrl) { | |
329 auto storage = base::MakeUnique<TestReadingListStorage>(this); | |
330 SetStorage(std::move(storage)); | |
331 model_->AddEntry(GURL("http://example.com"), "sample"); | |
332 ClearCounts(); | |
333 EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
334 nullptr); | |
335 EXPECT_EQ(model_->unread_size(), 1u); | |
336 model_->RemoveEntryByURL(GURL("http://example.com")); | |
337 AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1); | |
338 AssertStorageCount(0, 1); | |
339 EXPECT_EQ(model_->unread_size(), 0u); | |
340 EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
341 nullptr); | |
342 | |
343 model_->AddEntry(GURL("http://example.com"), "sample"); | |
344 model_->MarkReadByURL(GURL("http://example.com")); | |
345 ClearCounts(); | |
346 EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
347 nullptr); | |
348 EXPECT_EQ(model_->read_size(), 1u); | |
349 model_->RemoveEntryByURL(GURL("http://example.com")); | |
350 AssertObserverCount(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1); | |
351 AssertStorageCount(0, 1); | |
352 EXPECT_EQ(model_->read_size(), 0u); | |
353 EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
354 nullptr); | |
355 } | |
356 | |
357 TEST_F(ReadingListModelTest, RemoveSyncEntryByUrl) { | |
358 auto storage = base::MakeUnique<TestReadingListStorage>(this); | |
359 SetStorage(std::move(storage)); | |
360 model_->AddEntry(GURL("http://example.com"), "sample"); | |
361 ClearCounts(); | |
362 EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
363 nullptr); | |
364 EXPECT_EQ(model_->unread_size(), 1u); | |
365 model_->SyncRemoveEntry(GURL("http://example.com")); | |
366 AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1); | |
367 AssertStorageCount(0, 0); | |
368 EXPECT_EQ(model_->unread_size(), 0u); | |
369 EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
370 nullptr); | |
371 | |
372 model_->AddEntry(GURL("http://example.com"), "sample"); | |
373 model_->MarkReadByURL(GURL("http://example.com")); | |
374 ClearCounts(); | |
375 EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
376 nullptr); | |
377 EXPECT_EQ(model_->read_size(), 1u); | |
378 model_->SyncRemoveEntry(GURL("http://example.com")); | |
379 AssertObserverCount(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1); | |
380 AssertStorageCount(0, 0); | |
381 EXPECT_EQ(model_->read_size(), 0u); | |
382 EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), | |
383 nullptr); | |
384 } | |
385 | |
386 TEST_F(ReadingListModelTest, ReadEntry) { | |
387 model_->AddEntry(GURL("http://example.com"), "sample"); | |
388 | |
389 ClearCounts(); | |
390 model_->MarkReadByURL(GURL("http://example.com")); | |
391 AssertObserverCount(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); | |
392 EXPECT_EQ(0ul, model_->unread_size()); | |
393 EXPECT_EQ(1ul, model_->read_size()); | |
394 EXPECT_FALSE(model_->HasUnseenEntries()); | |
395 | |
396 const ReadingListEntry& other_entry = model_->GetReadEntryAtIndex(0); | |
397 EXPECT_EQ(GURL("http://example.com"), other_entry.URL()); | |
398 EXPECT_EQ("sample", other_entry.Title()); | |
399 } | |
400 | |
401 TEST_F(ReadingListModelTest, EntryFromURL) { | |
402 GURL url1("http://example.com"); | |
403 GURL url2("http://example2.com"); | |
404 std::string entry1_title = "foo bar qux"; | |
405 model_->AddEntry(url1, entry1_title); | |
406 | |
407 // Check call with nullptr |read| parameter. | |
408 const ReadingListEntry* entry1 = model_->GetEntryFromURL(url1, nullptr); | |
409 EXPECT_NE(nullptr, entry1); | |
410 EXPECT_EQ(entry1_title, entry1->Title()); | |
411 | |
412 bool read; | |
413 entry1 = model_->GetEntryFromURL(url1, &read); | |
414 EXPECT_NE(nullptr, entry1); | |
415 EXPECT_EQ(entry1_title, entry1->Title()); | |
416 EXPECT_EQ(read, false); | |
417 model_->MarkReadByURL(url1); | |
418 entry1 = model_->GetEntryFromURL(url1, &read); | |
419 EXPECT_NE(nullptr, entry1); | |
420 EXPECT_EQ(entry1_title, entry1->Title()); | |
421 EXPECT_EQ(read, true); | |
422 | |
423 const ReadingListEntry* entry2 = model_->GetEntryFromURL(url2, &read); | |
424 EXPECT_EQ(nullptr, entry2); | |
425 } | |
426 | |
427 TEST_F(ReadingListModelTest, UnreadEntry) { | |
428 // Setup. | |
429 model_->AddEntry(GURL("http://example.com"), "sample"); | |
430 model_->MarkReadByURL(GURL("http://example.com")); | |
431 ClearCounts(); | |
432 ASSERT_EQ(0ul, model_->unread_size()); | |
433 ASSERT_EQ(1ul, model_->read_size()); | |
434 | |
435 // Action. | |
436 model_->MarkUnreadByURL(GURL("http://example.com")); | |
437 | |
438 // Tests. | |
439 AssertObserverCount(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); | |
440 EXPECT_EQ(1ul, model_->unread_size()); | |
441 EXPECT_EQ(0ul, model_->read_size()); | |
442 EXPECT_TRUE(model_->HasUnseenEntries()); | |
443 | |
444 const ReadingListEntry& other_entry = model_->GetUnreadEntryAtIndex(0); | |
445 EXPECT_EQ(GURL("http://example.com"), other_entry.URL()); | |
446 EXPECT_EQ("sample", other_entry.Title()); | |
447 } | |
448 | |
449 TEST_F(ReadingListModelTest, BatchUpdates) { | |
450 auto token = model_->BeginBatchUpdates(); | |
451 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
452 EXPECT_TRUE(model_->IsPerformingBatchUpdates()); | |
453 | |
454 delete token.release(); | |
455 AssertObserverCount(1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
456 EXPECT_FALSE(model_->IsPerformingBatchUpdates()); | |
457 } | |
458 | |
459 TEST_F(ReadingListModelTest, BatchUpdatesReentrant) { | |
460 // When two updates happen at the same time, the notification is only sent | |
461 // for beginning of first update and completion of last update. | |
462 EXPECT_FALSE(model_->IsPerformingBatchUpdates()); | |
463 | |
464 auto token = model_->BeginBatchUpdates(); | |
465 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
466 EXPECT_TRUE(model_->IsPerformingBatchUpdates()); | |
467 | |
468 auto second_token = model_->BeginBatchUpdates(); | |
469 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
470 EXPECT_TRUE(model_->IsPerformingBatchUpdates()); | |
471 | |
472 delete token.release(); | |
473 AssertObserverCount(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
474 EXPECT_TRUE(model_->IsPerformingBatchUpdates()); | |
475 | |
476 delete second_token.release(); | |
477 AssertObserverCount(1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
478 EXPECT_FALSE(model_->IsPerformingBatchUpdates()); | |
479 | |
480 // Consequent updates send notifications. | |
481 auto third_token = model_->BeginBatchUpdates(); | |
482 AssertObserverCount(1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
483 EXPECT_TRUE(model_->IsPerformingBatchUpdates()); | |
484 | |
485 delete third_token.release(); | |
486 AssertObserverCount(1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
487 EXPECT_FALSE(model_->IsPerformingBatchUpdates()); | |
488 } | |
489 | |
490 TEST_F(ReadingListModelTest, UpdateEntryTitle) { | |
491 const GURL gurl("http://example.com"); | |
492 const ReadingListEntry& entry = model_->AddEntry(gurl, "sample"); | |
493 ClearCounts(); | |
494 | |
495 model_->SetEntryTitle(gurl, "ping"); | |
496 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1); | |
497 EXPECT_EQ("ping", entry.Title()); | |
498 } | |
499 | |
500 TEST_F(ReadingListModelTest, UpdateEntryState) { | |
501 const GURL gurl("http://example.com"); | |
502 const ReadingListEntry& entry = model_->AddEntry(gurl, "sample"); | |
503 ClearCounts(); | |
504 | |
505 model_->SetEntryDistilledState(gurl, ReadingListEntry::PROCESSING); | |
506 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1); | |
507 EXPECT_EQ(ReadingListEntry::PROCESSING, entry.DistilledState()); | |
508 } | |
509 | |
510 TEST_F(ReadingListModelTest, UpdateDistilledPath) { | |
511 const GURL gurl("http://example.com"); | |
512 const ReadingListEntry& entry = model_->AddEntry(gurl, "sample"); | |
513 ClearCounts(); | |
514 | |
515 model_->SetEntryDistilledPath(gurl, base::FilePath("distilled/page.html")); | |
516 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1); | |
517 EXPECT_EQ(ReadingListEntry::PROCESSED, entry.DistilledState()); | |
518 EXPECT_EQ(base::FilePath("distilled/page.html"), entry.DistilledPath()); | |
519 } | |
520 | |
521 TEST_F(ReadingListModelTest, UpdateReadEntryTitle) { | |
522 const GURL gurl("http://example.com"); | |
523 model_->AddEntry(gurl, "sample"); | |
524 model_->MarkReadByURL(gurl); | |
525 const ReadingListEntry& entry = model_->GetReadEntryAtIndex(0); | |
526 ClearCounts(); | |
527 | |
528 model_->SetEntryTitle(gurl, "ping"); | |
529 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1); | |
530 EXPECT_EQ("ping", entry.Title()); | |
531 } | |
532 | |
533 TEST_F(ReadingListModelTest, UpdateReadEntryState) { | |
534 const GURL gurl("http://example.com"); | |
535 model_->AddEntry(gurl, "sample"); | |
536 model_->MarkReadByURL(gurl); | |
537 const ReadingListEntry& entry = model_->GetReadEntryAtIndex(0); | |
538 ClearCounts(); | |
539 | |
540 model_->SetEntryDistilledState(gurl, ReadingListEntry::PROCESSING); | |
541 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1); | |
542 EXPECT_EQ(ReadingListEntry::PROCESSING, entry.DistilledState()); | |
543 } | |
544 | |
545 TEST_F(ReadingListModelTest, UpdateReadDistilledPath) { | |
546 const GURL gurl("http://example.com"); | |
547 model_->AddEntry(gurl, "sample"); | |
548 model_->MarkReadByURL(gurl); | |
549 const ReadingListEntry& entry = model_->GetReadEntryAtIndex(0); | |
550 ClearCounts(); | |
551 | |
552 model_->SetEntryDistilledPath(gurl, base::FilePath("distilled/page.html")); | |
553 AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1); | |
554 EXPECT_EQ(ReadingListEntry::PROCESSED, entry.DistilledState()); | |
555 EXPECT_EQ(base::FilePath("distilled/page.html"), entry.DistilledPath()); | |
556 } | |
557 | |
558 // Tests that the callback is called when the entry is unread. | |
559 TEST_F(ReadingListModelTest, CallbackEntryURLUnread) { | |
560 // Setup. | |
561 model_->AddEntry(callback_url, callback_title); | |
562 | |
563 ASSERT_EQ(0UL, model_->read_size()); | |
564 ASSERT_EQ(1UL, model_->unread_size()); | |
565 | |
566 // Action. | |
567 bool result = model_->CallbackEntryURL( | |
568 callback_url, | |
569 base::Bind(&ReadingListModelTest::Callback, base::Unretained(this))); | |
570 | |
571 // Test. | |
572 EXPECT_TRUE(result); | |
573 EXPECT_TRUE(CallbackCalled()); | |
574 } | |
575 | |
576 // Tests that the callback is called when the entry is read. | |
577 TEST_F(ReadingListModelTest, CallbackEntryURLRead) { | |
578 // Setup. | |
579 model_->AddEntry(callback_url, callback_title); | |
580 model_->MarkReadByURL(callback_url); | |
581 | |
582 ASSERT_EQ(1UL, model_->read_size()); | |
583 ASSERT_EQ(0UL, model_->unread_size()); | |
584 | |
585 // Action. | |
586 bool result = model_->CallbackEntryURL( | |
587 callback_url, | |
588 base::Bind(&ReadingListModelTest::Callback, base::Unretained(this))); | |
589 | |
590 // Test. | |
591 EXPECT_TRUE(result); | |
592 EXPECT_TRUE(CallbackCalled()); | |
593 } | |
594 | |
595 // Tests that the callback is not called when the entry is not present. | |
596 TEST_F(ReadingListModelTest, CallbackEntryURLNotPresent) { | |
597 // Setup. | |
598 const GURL gurl("http://foo.bar"); | |
599 ASSERT_NE(gurl, callback_url); | |
600 model_->AddEntry(gurl, callback_title); | |
601 | |
602 // Action. | |
603 bool result = model_->CallbackEntryURL( | |
604 callback_url, | |
605 base::Bind(&ReadingListModelTest::Callback, base::Unretained(this))); | |
606 | |
607 // Test. | |
608 EXPECT_FALSE(result); | |
609 EXPECT_FALSE(CallbackCalled()); | |
610 } | |
611 | |
612 // Tests that ReadingListModel calls CallbackModelBeingDeleted when destroyed. | |
613 TEST_F(ReadingListModelTest, CallbackModelBeingDeleted) { | |
614 AssertObserverCount(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
615 model_.reset(); | |
616 AssertObserverCount(1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); | |
617 } | |
618 | |
619 } // namespace | |
OLD | NEW |