| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/feed/core/feed_storage_database.h" |
| |
| #include <map> |
| |
| #include "base/test/scoped_task_environment.h" |
| #include "components/feed/core/proto/feed_storage.pb.h" |
| #include "components/feed/core/time_serialization.h" |
| #include "components/leveldb_proto/testing/fake_db.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using leveldb_proto::test::FakeDB; |
| using testing::Mock; |
| using testing::NotNull; |
| using testing::_; |
| |
| namespace feed { |
| |
| namespace { |
| const std::string kContentKeyPrefix = "ContentKey"; |
| const std::string kContentKey1 = "ContentKey1"; |
| const std::string kContentKey2 = "ContentKey2"; |
| const std::string kContentKey3 = "ContentKey3"; |
| const std::string kContentData1 = "Content Data1"; |
| const std::string kContentData2 = "Content Data2"; |
| const std::string kContentData3 = "Content Data3"; |
| const std::string kJournalKey1 = "JournalKey1"; |
| const std::string kJournalKey2 = "JournalKey2"; |
| const std::string kJournalKey3 = "JournalKey3"; |
| const std::string kJournalData1 = "Journal Data1"; |
| const std::string kJournalData2 = "Journal Data2"; |
| const std::string kJournalData3 = "Journal Data3"; |
| const std::string kJournalData4 = "Journal Data4"; |
| const std::string kJournalData5 = "Journal Data5"; |
| const std::string kJournalData6 = "Journal Data6"; |
| } // namespace |
| |
| class FeedStorageDatabaseTest : public testing::Test { |
| public: |
| FeedStorageDatabaseTest() : storage_db_(nullptr) {} |
| |
| void CreateDatabase(bool init_database) { |
| // The FakeDBs are owned by |feed_db_|, so clear our pointers before |
| // resetting |feed_db_| itself. |
| storage_db_ = nullptr; |
| // Explicitly destroy any existing database before creating a new one. |
| feed_db_.reset(); |
| |
| auto storage_db = |
| std::make_unique<FakeDB<FeedStorageProto>>(&storage_db_storage_); |
| |
| storage_db_ = storage_db.get(); |
| feed_db_ = std::make_unique<FeedStorageDatabase>(base::FilePath(), |
| std::move(storage_db)); |
| if (init_database) { |
| storage_db_->InitCallback(true); |
| ASSERT_TRUE(db()->IsInitialized()); |
| } |
| } |
| |
| void InjectContentStorageProto(const std::string& key, |
| const std::string& data) { |
| FeedStorageProto storage_proto; |
| storage_proto.set_key(key); |
| storage_proto.set_content_data(data); |
| storage_db_storage_["cs-" + key] = storage_proto; |
| } |
| |
| void InjectJournalStorageProto(const std::string& key, |
| const std::vector<std::string>& entries) { |
| FeedStorageProto storage_proto; |
| storage_proto.set_key(key); |
| for (const std::string& entry : entries) { |
| storage_proto.add_journal_data(entry); |
| } |
| storage_db_storage_["js-" + key] = storage_proto; |
| } |
| |
| void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); } |
| |
| FakeDB<FeedStorageProto>* storage_db() { return storage_db_; } |
| |
| FeedStorageDatabase* db() { return feed_db_.get(); } |
| |
| MOCK_METHOD1(OnContentEntriesReceived, |
| void(std::vector<std::pair<std::string, std::string>>)); |
| MOCK_METHOD1(OnContentKeyReceived, void(std::vector<std::string>)); |
| MOCK_METHOD1(OnJournalEntryReceived, void(std::vector<std::string>)); |
| MOCK_METHOD1(OnJournalEntriesReceived, |
| void(std::vector<std::vector<std::string>>)); |
| MOCK_METHOD1(OnStorageCommitted, void(bool)); |
| |
| private: |
| base::test::ScopedTaskEnvironment scoped_task_environment_; |
| |
| std::map<std::string, FeedStorageProto> storage_db_storage_; |
| |
| // Owned by |feed_db_|. |
| FakeDB<FeedStorageProto>* storage_db_; |
| |
| std::unique_ptr<FeedStorageDatabase> feed_db_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FeedStorageDatabaseTest); |
| }; |
| |
| TEST_F(FeedStorageDatabaseTest, Init) { |
| ASSERT_FALSE(db()); |
| |
| CreateDatabase(/*init_database=*/false); |
| |
| storage_db()->InitCallback(true); |
| EXPECT_TRUE(db()->IsInitialized()); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, LoadContentAfterInitSuccess) { |
| CreateDatabase(/*init_database=*/true); |
| |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)); |
| db()->LoadContent( |
| {kContentKey1}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, LoadContentsEntries) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1| and |kContentKey2|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| InjectJournalStorageProto(kJournalKey2, {kJournalData4, kJournalData5}); |
| InjectJournalStorageProto(kJournalKey3, {kJournalData6}); |
| |
| // Try to Load |kContentKey2| and |kContentKey3|, only |kContentKey2| should |
| // return. |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)) |
| .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { |
| ASSERT_EQ(results.size(), 1U); |
| EXPECT_EQ(results[0].first, kContentKey2); |
| EXPECT_EQ(results[0].second, kContentData2); |
| }); |
| db()->LoadContent( |
| {kContentKey2, kContentKey3}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, LoadContentsEntriesByPrefix) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1|, |kContentKey2|, |kJournalKey1|, |kJournalKey2|, |
| // |kJournalKey3|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| InjectJournalStorageProto(kJournalKey2, {kJournalData4, kJournalData5}); |
| InjectJournalStorageProto(kJournalKey3, {kJournalData6}); |
| |
| // Try to Load "ContentKey", both |kContentKey1| and |kContentKey2| should |
| // return. |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)) |
| .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { |
| ASSERT_EQ(results.size(), 2U); |
| EXPECT_EQ(results[0].first, kContentKey1); |
| EXPECT_EQ(results[0].second, kContentData1); |
| EXPECT_EQ(results[1].first, kContentKey2); |
| EXPECT_EQ(results[1].second, kContentData2); |
| }); |
| db()->LoadContentByPrefix( |
| kContentKeyPrefix, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, LoadAllContentKeys) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1|, |kContentKey2|, |kJournalKey1|, |kJournalKey2|, |
| // |kJournalKey3|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| InjectJournalStorageProto(kJournalKey2, {kJournalData4, kJournalData5}); |
| InjectJournalStorageProto(kJournalKey3, {kJournalData6}); |
| |
| EXPECT_CALL(*this, OnContentKeyReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 2U); |
| EXPECT_EQ(results[0], kContentKey1); |
| EXPECT_EQ(results[1], kContentKey2); |
| }); |
| db()->LoadAllContentKeys(base::BindOnce( |
| &FeedStorageDatabaseTest::OnContentKeyReceived, base::Unretained(this))); |
| storage_db()->LoadKeysCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, SaveContent) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1|, |kContentKey2|, |kJournalKey1|, |kJournalKey2|, |
| // |kJournalKey3|. |
| std::vector<std::pair<std::string, std::string>> entries; |
| entries.push_back(std::make_pair(kContentKey1, kContentData1)); |
| entries.push_back(std::make_pair(kContentKey2, kContentData2)); |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->SaveContent(std::move(entries), |
| base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->UpdateCallback(true); |
| |
| // Make sure they're there. |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)) |
| .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { |
| ASSERT_EQ(results.size(), 2U); |
| EXPECT_EQ(results[0].first, kContentKey1); |
| EXPECT_EQ(results[0].second, kContentData1); |
| EXPECT_EQ(results[1].first, kContentKey2); |
| EXPECT_EQ(results[1].second, kContentData2); |
| }); |
| db()->LoadContent( |
| {kContentKey1, kContentKey2}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, DeleteContent) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1| and |kContentKey2|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| |
| // Delete |kContentKey2| and |kContentKey3| |
| std::vector<std::string> keys; |
| keys.push_back(kContentKey2); |
| keys.push_back(kContentKey3); |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->DeleteContent( |
| std::move(keys), |
| base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->UpdateCallback(true); |
| |
| // Make sure only |kContentKey2| got deleted. |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)) |
| .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { |
| EXPECT_EQ(results.size(), 1U); |
| EXPECT_EQ(results[0].first, kContentKey1); |
| EXPECT_EQ(results[0].second, kContentData1); |
| }); |
| db()->LoadContent( |
| {kContentKey1, kContentKey2}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, DeleteContentByPrefix) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1| and |kContentKey2|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| |
| // Delete |kContentKey1| and |kContentKey2| |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->DeleteContentByPrefix( |
| kContentKeyPrefix, |
| base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->UpdateCallback(true); |
| |
| // Make sure |kContentKey1| and |kContentKey2| got deleted. |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)) |
| .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { |
| EXPECT_EQ(results.size(), 0U); |
| }); |
| db()->LoadContent( |
| {kContentKey1, kContentKey2}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, DeleteAllContent) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1| and |kContentKey2|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| |
| // Store |kJournalKey1|, |kJournalKey2|, |kJournalKey3|. |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| InjectJournalStorageProto(kJournalKey2, {kJournalData4, kJournalData5}); |
| InjectJournalStorageProto(kJournalKey3, {kJournalData6}); |
| |
| // Delete all content, meaning |kContentKey1| and |kContentKey2| are expected |
| // to be deleted. |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->DeleteAllContent(base::BindOnce( |
| &FeedStorageDatabaseTest::OnStorageCommitted, base::Unretained(this))); |
| storage_db()->UpdateCallback(true); |
| |
| // Make sure |kContentKey1| and |kContentKey2| got deleted. |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)) |
| .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { |
| EXPECT_EQ(results.size(), 0U); |
| }); |
| db()->LoadContent( |
| {kContentKey1, kContentKey2}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| |
| // Make sure all journals are there. |
| EXPECT_CALL(*this, OnJournalEntriesReceived(_)) |
| .WillOnce([](std::vector<std::vector<std::string>> results) { |
| ASSERT_EQ(results.size(), 3U); |
| }); |
| db()->LoadAllJournals( |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, LoadJournalEntry) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kJournalKey1|. |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| |
| // Try to Load |kJournalKey1|. |
| EXPECT_CALL(*this, OnJournalEntryReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 3U); |
| EXPECT_EQ(results[0], kJournalData1); |
| EXPECT_EQ(results[1], kJournalData2); |
| EXPECT_EQ(results[2], kJournalData3); |
| }); |
| db()->LoadJournal( |
| kJournalKey1, |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntryReceived, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, LoadNonExistingJournalEntry) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Try to Load |kJournalKey1|. |
| EXPECT_CALL(*this, OnJournalEntryReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 0U); |
| }); |
| db()->LoadJournal( |
| kJournalKey1, |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntryReceived, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, LoadAllJournals) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1|, |kContentKey2|, |kJournalKey1|, |kJournalKey2|, |
| // |kJournalKey3|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| InjectJournalStorageProto(kJournalKey2, {kJournalData4, kJournalData5}); |
| InjectJournalStorageProto(kJournalKey3, {kJournalData6}); |
| |
| EXPECT_CALL(*this, OnJournalEntriesReceived(_)) |
| .WillOnce([](std::vector<std::vector<std::string>> results) { |
| ASSERT_EQ(results.size(), 3U); |
| EXPECT_EQ(results[0][0], kJournalData1); |
| EXPECT_EQ(results[0][1], kJournalData2); |
| EXPECT_EQ(results[0][2], kJournalData3); |
| EXPECT_EQ(results[1][0], kJournalData4); |
| EXPECT_EQ(results[1][1], kJournalData5); |
| EXPECT_EQ(results[2][0], kJournalData6); |
| }); |
| db()->LoadAllJournals( |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, AppendToJournal_WhenJournalExists) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Save |kContentKey1| |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->AppendToJournal( |
| kJournalKey1, {kJournalData1, kJournalData2}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| storage_db()->UpdateCallback(true); |
| |
| // Make sure they're there. |
| EXPECT_CALL(*this, OnJournalEntryReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 2U); |
| EXPECT_EQ(results[0], kJournalData1); |
| EXPECT_EQ(results[1], kJournalData2); |
| }); |
| db()->LoadJournal( |
| kJournalKey1, |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntryReceived, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| |
| Mock::VerifyAndClearExpectations(this); |
| |
| // Append more for |kContentKey1| |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->AppendToJournal( |
| kJournalKey1, {kJournalData3, kJournalData4, kJournalData5}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| storage_db()->UpdateCallback(true); |
| |
| // Check new instances are there. |
| EXPECT_CALL(*this, OnJournalEntryReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 5U); |
| EXPECT_EQ(results[0], kJournalData1); |
| EXPECT_EQ(results[1], kJournalData2); |
| EXPECT_EQ(results[2], kJournalData3); |
| EXPECT_EQ(results[3], kJournalData4); |
| EXPECT_EQ(results[4], kJournalData5); |
| }); |
| db()->LoadJournal( |
| kJournalKey1, |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntryReceived, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, AppendToJournal_WhenJournalMissing) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Append data for |kContentKey1| |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->AppendToJournal( |
| kJournalKey1, {kJournalData1, kJournalData2, kJournalData3}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| storage_db()->UpdateCallback(true); |
| |
| // Check new data are there. |
| EXPECT_CALL(*this, OnJournalEntryReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 3U); |
| EXPECT_EQ(results[0], kJournalData1); |
| EXPECT_EQ(results[1], kJournalData2); |
| EXPECT_EQ(results[2], kJournalData3); |
| }); |
| db()->LoadJournal( |
| kJournalKey1, |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntryReceived, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, CopyJournal) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Save |kContentKey1|. |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| |
| // Copy |kContentKey1| to |kContentKey2|. |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->CopyJournal(kJournalKey1, kJournalKey2, |
| base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| storage_db()->UpdateCallback(true); |
| |
| // Check new journal is there. |
| EXPECT_CALL(*this, OnJournalEntryReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 3U); |
| EXPECT_EQ(results[0], kJournalData1); |
| EXPECT_EQ(results[1], kJournalData2); |
| EXPECT_EQ(results[2], kJournalData3); |
| }); |
| db()->LoadJournal( |
| kJournalKey2, |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntryReceived, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| |
| Mock::VerifyAndClearExpectations(this); |
| |
| // Check first journal is still there. |
| EXPECT_CALL(*this, OnJournalEntryReceived(_)) |
| .WillOnce([](std::vector<std::string> results) { |
| ASSERT_EQ(results.size(), 3U); |
| EXPECT_EQ(results[0], kJournalData1); |
| EXPECT_EQ(results[1], kJournalData2); |
| EXPECT_EQ(results[2], kJournalData3); |
| }); |
| db()->LoadJournal( |
| kJournalKey1, |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntryReceived, |
| base::Unretained(this))); |
| storage_db()->GetCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, DeleteJournal) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kJournalKey1|, |kJournalKey2|, |kJournalKey3|. |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| InjectJournalStorageProto(kJournalKey2, {kJournalData4, kJournalData5}); |
| InjectJournalStorageProto(kJournalKey3, {kJournalData6}); |
| |
| // Delete |kJournalKey2|. |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->DeleteJournal( |
| kJournalKey2, base::BindOnce(&FeedStorageDatabaseTest::OnStorageCommitted, |
| base::Unretained(this))); |
| storage_db()->UpdateCallback(true); |
| |
| // Make sure |kJournalKey2| got deleted. |
| EXPECT_CALL(*this, OnJournalEntriesReceived(_)) |
| .WillOnce([](std::vector<std::vector<std::string>> results) { |
| ASSERT_EQ(results.size(), 2U); |
| EXPECT_EQ(results[0][0], kJournalData1); |
| EXPECT_EQ(results[0][1], kJournalData2); |
| EXPECT_EQ(results[0][2], kJournalData3); |
| EXPECT_EQ(results[1][0], kJournalData6); |
| }); |
| db()->LoadAllJournals( |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| TEST_F(FeedStorageDatabaseTest, DeleteAllJournals) { |
| CreateDatabase(/*init_database=*/true); |
| |
| // Store |kContentKey1| and |kContentKey2|. |
| InjectContentStorageProto(kContentKey1, kContentData1); |
| InjectContentStorageProto(kContentKey2, kContentData2); |
| |
| // Store |kJournalKey1|, |kJournalKey2|, |kJournalKey3|. |
| InjectJournalStorageProto(kJournalKey1, |
| {kJournalData1, kJournalData2, kJournalData3}); |
| InjectJournalStorageProto(kJournalKey2, {kJournalData4, kJournalData5}); |
| InjectJournalStorageProto(kJournalKey3, {kJournalData6}); |
| |
| // Delete all journals, meaning |kJournalKey1|, |kJournalKey2| and |
| // |kJournalKey3| are expected to be deleted. |
| EXPECT_CALL(*this, OnStorageCommitted(true)); |
| db()->DeleteAllJournals(base::BindOnce( |
| &FeedStorageDatabaseTest::OnStorageCommitted, base::Unretained(this))); |
| storage_db()->UpdateCallback(true); |
| |
| // Make sure all journals got deleted. |
| EXPECT_CALL(*this, OnJournalEntriesReceived(_)) |
| .WillOnce([](std::vector<std::vector<std::string>> results) { |
| ASSERT_EQ(results.size(), 0U); |
| }); |
| db()->LoadAllJournals( |
| base::BindOnce(&FeedStorageDatabaseTest::OnJournalEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| |
| // Make sure all content are still there. |
| EXPECT_CALL(*this, OnContentEntriesReceived(_)) |
| .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { |
| ASSERT_EQ(results.size(), 2U); |
| EXPECT_EQ(results[0].first, kContentKey1); |
| EXPECT_EQ(results[0].second, kContentData1); |
| EXPECT_EQ(results[1].first, kContentKey2); |
| EXPECT_EQ(results[1].second, kContentData2); |
| }); |
| db()->LoadContent( |
| {kContentKey1, kContentKey2}, |
| base::BindOnce(&FeedStorageDatabaseTest::OnContentEntriesReceived, |
| base::Unretained(this))); |
| storage_db()->LoadCallback(true); |
| } |
| |
| } // namespace feed |