Index: ios/chrome/browser/reading_list/reading_list_model_unittest.cc |
diff --git a/ios/chrome/browser/reading_list/reading_list_model_unittest.cc b/ios/chrome/browser/reading_list/reading_list_model_unittest.cc |
index 1e97064edba99b6ff1e870c9ac20007c0a77526b..4913e9733edc8319426a61df840346b31f10089f 100644 |
--- a/ios/chrome/browser/reading_list/reading_list_model_unittest.cc |
+++ b/ios/chrome/browser/reading_list/reading_list_model_unittest.cc |
@@ -3,7 +3,9 @@ |
// found in the LICENSE file. |
#include "base/bind.h" |
+#include "base/memory/ptr_util.h" |
#include "ios/chrome/browser/reading_list/reading_list_model_impl.h" |
+#include "ios/chrome/browser/reading_list/reading_list_model_storage.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace { |
@@ -11,7 +13,68 @@ namespace { |
const GURL callback_url("http://example.com"); |
const std::string callback_title("test title"); |
+class TestReadingListStorageObserver { |
+ public: |
+ virtual void ReadingListDidSaveEntry() = 0; |
+ virtual void ReadingListDidRemoveEntry() = 0; |
+}; |
+ |
+class TestReadingListStorage : public ReadingListModelStorage { |
+ public: |
+ TestReadingListStorage(TestReadingListStorageObserver* observer) |
+ : read_(new std::vector<ReadingListEntry>()), |
+ unread_(new std::vector<ReadingListEntry>()), |
+ observer_(observer) {} |
+ |
+ void AddSampleEntries() { |
+ ReadingListEntry read_a(GURL("http://read_a.com"), "read_a"); |
+ ReadingListEntry read_b(GURL("http://read_b.com"), "read_b"); |
+ ReadingListEntry read_c(GURL("http://read_c.com"), "read_c"); |
+ read_->push_back(std::move(read_c)); |
+ read_->push_back(std::move(read_a)); |
+ read_->push_back(std::move(read_b)); |
+ ReadingListEntry unread_a(GURL("http://unread_a.com"), "unread_a"); |
+ ReadingListEntry unread_b(GURL("http://unread_b.com"), "unread_b"); |
+ ReadingListEntry unread_c(GURL("http://unread_c.com"), "unread_c"); |
+ ReadingListEntry unread_d(GURL("http://unread_d.com"), "unread_d"); |
+ unread_->push_back(std::move(unread_a)); |
+ unread_->push_back(std::move(unread_d)); |
+ unread_->push_back(std::move(unread_c)); |
+ unread_->push_back(std::move(unread_b)); |
+ } |
+ |
+ void SetReadingListModel(ReadingListModel* model, |
+ ReadingListStoreDelegate* delegate_) override { |
+ delegate_->StoreLoaded(std::move(unread_), std::move(read_)); |
+ } |
+ |
+ syncer::ModelTypeSyncBridge* GetModelTypeSyncBridge() override { |
+ return nullptr; |
+ } |
+ |
+ std::unique_ptr<ScopedBatchUpdate> EnsureBatchCreated() override { |
+ return std::unique_ptr<ScopedBatchUpdate>(); |
+ } |
+ |
+ // Saves or updates an entry. If the entry is not yet in the database, it is |
+ // created. |
+ void SaveEntry(const ReadingListEntry& entry, bool read) override { |
+ observer_->ReadingListDidSaveEntry(); |
+ } |
+ |
+ // Removed an entry from the storage. |
+ void RemoveEntry(const ReadingListEntry& entry) override { |
+ observer_->ReadingListDidRemoveEntry(); |
+ } |
+ |
+ private: |
+ std::unique_ptr<std::vector<ReadingListEntry>> read_; |
+ std::unique_ptr<std::vector<ReadingListEntry>> unread_; |
+ TestReadingListStorageObserver* observer_; |
+}; |
+ |
class ReadingListModelTest : public ReadingListModelObserver, |
+ public TestReadingListStorageObserver, |
public testing::Test { |
public: |
ReadingListModelTest() |
@@ -21,13 +84,21 @@ class ReadingListModelTest : public ReadingListModelObserver, |
} |
~ReadingListModelTest() override {} |
+ void SetStorage(std::unique_ptr<TestReadingListStorage> storage) { |
+ model_ = |
+ base::MakeUnique<ReadingListModelImpl>(std::move(storage), nullptr); |
+ ClearCounts(); |
+ model_->AddObserver(this); |
+ } |
+ |
void ClearCounts() { |
observer_loaded_ = observer_started_batch_update_ = |
observer_completed_batch_update_ = observer_deleted_ = |
observer_remove_unread_ = observer_remove_read_ = observer_move_ = |
observer_add_unread_ = observer_add_read_ = |
observer_update_unread_ = observer_update_read_ = |
- observer_did_apply_ = 0; |
+ observer_did_apply_ = storage_saved_ = |
+ storage_removed_ = 0; |
} |
void AssertObserverCount(int observer_loaded, |
@@ -57,6 +128,11 @@ class ReadingListModelTest : public ReadingListModelObserver, |
ASSERT_EQ(observer_did_apply, observer_did_apply_); |
} |
+ void AssertStorageCount(int storage_saved, int storage_removed) { |
+ ASSERT_EQ(storage_saved, storage_saved_); |
+ ASSERT_EQ(storage_removed, storage_removed_); |
+ } |
+ |
// ReadingListModelObserver |
void ReadingListModelLoaded(const ReadingListModel* model) override { |
observer_loaded_ += 1; |
@@ -77,7 +153,8 @@ class ReadingListModelTest : public ReadingListModelObserver, |
observer_remove_unread_ += 1; |
} |
void ReadingListWillMoveEntry(const ReadingListModel* model, |
- size_t index) override { |
+ size_t index, |
+ bool read) override { |
observer_move_ += 1; |
} |
void ReadingListWillRemoveReadEntry(const ReadingListModel* model, |
@@ -103,6 +180,10 @@ class ReadingListModelTest : public ReadingListModelObserver, |
void ReadingListDidApplyChanges(ReadingListModel* model) override { |
observer_did_apply_ += 1; |
} |
+ |
+ void ReadingListDidSaveEntry() override { storage_saved_ += 1; } |
+ void ReadingListDidRemoveEntry() override { storage_removed_ += 1; } |
+ |
void Callback(const ReadingListEntry& entry) { |
EXPECT_EQ(callback_url, entry.URL()); |
EXPECT_EQ(callback_title, entry.Title()); |
@@ -124,6 +205,8 @@ class ReadingListModelTest : public ReadingListModelObserver, |
int observer_update_unread_; |
int observer_update_read_; |
int observer_did_apply_; |
+ int storage_saved_; |
+ int storage_removed_; |
bool callback_called_; |
std::unique_ptr<ReadingListModelImpl> model_; |
@@ -139,14 +222,37 @@ TEST_F(ReadingListModelTest, EmptyLoaded) { |
AssertObserverCount(1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); |
} |
+TEST_F(ReadingListModelTest, ModelLoaded) { |
+ ClearCounts(); |
+ auto storage = base::MakeUnique<TestReadingListStorage>(this); |
+ storage->AddSampleEntries(); |
+ SetStorage(std::move(storage)); |
+ |
+ AssertObserverCount(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); |
+ EXPECT_EQ(model_->read_size(), 3u); |
+ EXPECT_EQ(model_->GetReadEntryAtIndex(0).Title(), "read_c"); |
+ EXPECT_EQ(model_->GetReadEntryAtIndex(1).Title(), "read_b"); |
+ EXPECT_EQ(model_->GetReadEntryAtIndex(2).Title(), "read_a"); |
+ |
+ EXPECT_EQ(model_->unread_size(), 4u); |
+ EXPECT_EQ(model_->GetUnreadEntryAtIndex(0).Title(), "unread_d"); |
+ EXPECT_EQ(model_->GetUnreadEntryAtIndex(1).Title(), "unread_c"); |
+ EXPECT_EQ(model_->GetUnreadEntryAtIndex(2).Title(), "unread_b"); |
+ EXPECT_EQ(model_->GetUnreadEntryAtIndex(3).Title(), "unread_a"); |
+} |
+ |
TEST_F(ReadingListModelTest, AddEntry) { |
+ auto storage = base::MakeUnique<TestReadingListStorage>(this); |
+ SetStorage(std::move(storage)); |
ClearCounts(); |
+ |
const ReadingListEntry& entry = |
model_->AddEntry(GURL("http://example.com"), "\n \tsample Test "); |
EXPECT_EQ(GURL("http://example.com"), entry.URL()); |
EXPECT_EQ("sample Test", entry.Title()); |
AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1); |
+ AssertStorageCount(1, 0); |
EXPECT_EQ(1ul, model_->unread_size()); |
EXPECT_EQ(0ul, model_->read_size()); |
EXPECT_TRUE(model_->HasUnseenEntries()); |
@@ -156,6 +262,107 @@ TEST_F(ReadingListModelTest, AddEntry) { |
EXPECT_EQ("sample Test", other_entry.Title()); |
} |
+TEST_F(ReadingListModelTest, SyncAddEntry) { |
+ auto storage = base::MakeUnique<TestReadingListStorage>(this); |
+ SetStorage(std::move(storage)); |
+ auto entry = |
+ base::MakeUnique<ReadingListEntry>(GURL("http://example.com"), "sample"); |
+ ClearCounts(); |
+ model_->AddEntry(GURL("http://example.com"), "sample"); |
+ model_->MarkReadByURL(GURL("http://example.com")); |
+ |
+ AssertObserverCount(0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 2); |
+ AssertStorageCount(2, 0); |
+ ASSERT_EQ(model_->unread_size(), 0u); |
+ ASSERT_EQ(model_->read_size(), 1u); |
+ ClearCounts(); |
+ |
+ // This entry is older, it should not replace the old one. |
+ model_->SyncAddEntry(std::move(entry), false); |
+ AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); |
+ AssertStorageCount(0, 0); |
+ ASSERT_EQ(model_->unread_size(), 0u); |
+ ASSERT_EQ(model_->read_size(), 1u); |
+ ClearCounts(); |
+ |
+ entry = |
+ base::MakeUnique<ReadingListEntry>(GURL("http://example.com"), "sample"); |
+ // This entry is newer, it should replace the old one and mark it unread. |
+ model_->SyncAddEntry(std::move(entry), false); |
+ AssertObserverCount(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); |
+ AssertStorageCount(1, 0); |
+ ASSERT_EQ(model_->unread_size(), 1u); |
+ ASSERT_EQ(model_->read_size(), 0u); |
+ ClearCounts(); |
+ |
+ entry = |
+ base::MakeUnique<ReadingListEntry>(GURL("http://example.com"), "sample"); |
+ // This entry is newer, it should replace the old one and mark it read. |
+ model_->SyncAddEntry(std::move(entry), true); |
+ AssertObserverCount(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); |
+ AssertStorageCount(1, 0); |
+ ASSERT_EQ(model_->unread_size(), 0u); |
+ ASSERT_EQ(model_->read_size(), 1u); |
+} |
+ |
+TEST_F(ReadingListModelTest, RemoveEntryByUrl) { |
+ auto storage = base::MakeUnique<TestReadingListStorage>(this); |
+ SetStorage(std::move(storage)); |
+ model_->AddEntry(GURL("http://example.com"), "sample"); |
+ ClearCounts(); |
+ EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+ EXPECT_EQ(model_->unread_size(), 1u); |
+ model_->RemoveEntryByURL(GURL("http://example.com")); |
+ AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1); |
+ AssertStorageCount(0, 1); |
+ EXPECT_EQ(model_->unread_size(), 0u); |
+ EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+ |
+ model_->AddEntry(GURL("http://example.com"), "sample"); |
+ model_->MarkReadByURL(GURL("http://example.com")); |
+ ClearCounts(); |
+ EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+ EXPECT_EQ(model_->read_size(), 1u); |
+ model_->RemoveEntryByURL(GURL("http://example.com")); |
+ AssertObserverCount(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1); |
+ AssertStorageCount(0, 1); |
+ EXPECT_EQ(model_->read_size(), 0u); |
+ EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+} |
+ |
+TEST_F(ReadingListModelTest, RemoveSyncEntryByUrl) { |
+ auto storage = base::MakeUnique<TestReadingListStorage>(this); |
+ SetStorage(std::move(storage)); |
+ model_->AddEntry(GURL("http://example.com"), "sample"); |
+ ClearCounts(); |
+ EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+ EXPECT_EQ(model_->unread_size(), 1u); |
+ model_->SyncRemoveEntry(GURL("http://example.com")); |
+ AssertObserverCount(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1); |
+ AssertStorageCount(0, 1); |
+ EXPECT_EQ(model_->unread_size(), 0u); |
+ EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+ |
+ model_->AddEntry(GURL("http://example.com"), "sample"); |
+ model_->MarkReadByURL(GURL("http://example.com")); |
+ ClearCounts(); |
+ EXPECT_NE(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+ EXPECT_EQ(model_->read_size(), 1u); |
+ model_->SyncRemoveEntry(GURL("http://example.com")); |
+ AssertObserverCount(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1); |
+ AssertStorageCount(0, 1); |
+ EXPECT_EQ(model_->read_size(), 0u); |
+ EXPECT_EQ(model_->GetEntryFromURL(GURL("http://example.com"), nullptr), |
+ nullptr); |
+} |
+ |
TEST_F(ReadingListModelTest, ReadEntry) { |
model_->AddEntry(GURL("http://example.com"), "sample"); |
@@ -177,15 +384,23 @@ TEST_F(ReadingListModelTest, EntryFromURL) { |
std::string entry1_title = "foo bar qux"; |
model_->AddEntry(url1, entry1_title); |
- const ReadingListEntry* entry1 = model_->GetEntryFromURL(url1); |
+ // Check call with nullptr |read| parameter. |
+ const ReadingListEntry* entry1 = model_->GetEntryFromURL(url1, nullptr); |
+ EXPECT_NE(nullptr, entry1); |
+ EXPECT_EQ(entry1_title, entry1->Title()); |
+ |
+ bool read; |
+ entry1 = model_->GetEntryFromURL(url1, &read); |
EXPECT_NE(nullptr, entry1); |
EXPECT_EQ(entry1_title, entry1->Title()); |
+ EXPECT_EQ(read, false); |
model_->MarkReadByURL(url1); |
- entry1 = model_->GetEntryFromURL(url1); |
+ entry1 = model_->GetEntryFromURL(url1, &read); |
EXPECT_NE(nullptr, entry1); |
EXPECT_EQ(entry1_title, entry1->Title()); |
+ EXPECT_EQ(read, true); |
- const ReadingListEntry* entry2 = model_->GetEntryFromURL(url2); |
+ const ReadingListEntry* entry2 = model_->GetEntryFromURL(url2, &read); |
EXPECT_EQ(nullptr, entry2); |
} |