diff options
author | pavely <pavely@chromium.org> | 2014-11-26 14:07:05 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-26 22:08:17 +0000 |
commit | 39dc7bac58f08244ecd344565c98f8d1b01fa3c5 (patch) | |
tree | 2d3eaf101ffeafbd6d4e19ad53f8943a9492a685 /sync/internal_api/attachments | |
parent | 0cd50ebcbdc0835c250ec44efc67891feb55c876 (diff) | |
download | chromium_src-39dc7bac58f08244ecd344565c98f8d1b01fa3c5.zip chromium_src-39dc7bac58f08244ecd344565c98f8d1b01fa3c5.tar.gz chromium_src-39dc7bac58f08244ecd344565c98f8d1b01fa3c5.tar.bz2 |
Synchronous creation of OnDiskAttachmentStore
AttachmentStore::CreateOnDiskStore synchronously returns reference to
attachment store. Internally it triggers asynchronous initialization on
background thread. If initialization fails then consecutive operations
with AttachmentStore fail with STORE_NOT_INITIALIZED.
BUG=436285
R=maniscalco@chromium.org
Review URL: https://codereview.chromium.org/757703004
Cr-Commit-Position: refs/heads/master@{#305891}
Diffstat (limited to 'sync/internal_api/attachments')
7 files changed, 214 insertions, 116 deletions
diff --git a/sync/internal_api/attachments/attachment_service_impl.cc b/sync/internal_api/attachments/attachment_service_impl.cc index 10f4790..dab7aa7 100644 --- a/sync/internal_api/attachments/attachment_service_impl.cc +++ b/sync/internal_api/attachments/attachment_service_impl.cc @@ -200,7 +200,8 @@ void AttachmentServiceImpl::ReadDone( AttachmentIdList::const_iterator iter = unavailable_attachment_ids->begin(); AttachmentIdList::const_iterator end = unavailable_attachment_ids->end(); - if (attachment_downloader_.get()) { + if (result != AttachmentStore::STORE_INITIALIZATION_FAILED && + attachment_downloader_.get()) { // Try to download locally unavailable attachments. for (; iter != end; ++iter) { attachment_downloader_->DownloadAttachment( @@ -227,6 +228,7 @@ void AttachmentServiceImpl::WriteDone( state->AddAttachment(attachment); break; case AttachmentStore::UNSPECIFIED_ERROR: + case AttachmentStore::STORE_INITIALIZATION_FAILED: state->AddUnavailableAttachmentId(attachment.GetId()); break; } diff --git a/sync/internal_api/attachments/attachment_service_impl_unittest.cc b/sync/internal_api/attachments/attachment_service_impl_unittest.cc index b83af16..713d155 100644 --- a/sync/internal_api/attachments/attachment_service_impl_unittest.cc +++ b/sync/internal_api/attachments/attachment_service_impl_unittest.cc @@ -24,6 +24,9 @@ class MockAttachmentStore : public AttachmentStore, public: MockAttachmentStore() {} + void Init(const InitCallback& callback) override { + } + void Read(const AttachmentIdList& ids, const ReadCallback& callback) override { read_ids.push_back(ids); diff --git a/sync/internal_api/attachments/attachment_store_handle.cc b/sync/internal_api/attachments/attachment_store_handle.cc index d770b6a..2807350 100644 --- a/sync/internal_api/attachments/attachment_store_handle.cc +++ b/sync/internal_api/attachments/attachment_store_handle.cc @@ -37,6 +37,13 @@ AttachmentStoreHandle::~AttachmentStoreHandle() { FROM_HERE, base::Bind(&NoOp, base::Passed(&backend_))); } +void AttachmentStoreHandle::Init(const InitCallback& callback) { + DCHECK(CalledOnValidThread()); + backend_task_runner_->PostTask( + FROM_HERE, base::Bind(&AttachmentStoreBase::Init, + base::Unretained(backend_.get()), callback)); +} + void AttachmentStoreHandle::Read(const AttachmentIdList& ids, const ReadCallback& callback) { DCHECK(CalledOnValidThread()); diff --git a/sync/internal_api/attachments/attachment_store_handle_unittest.cc b/sync/internal_api/attachments/attachment_store_handle_unittest.cc index 0764ee0..9f82a78 100644 --- a/sync/internal_api/attachments/attachment_store_handle_unittest.cc +++ b/sync/internal_api/attachments/attachment_store_handle_unittest.cc @@ -21,13 +21,15 @@ namespace { class MockAttachmentStore : public AttachmentStoreBase { public: - MockAttachmentStore(const base::Closure& read_called, + MockAttachmentStore(const base::Closure& init_called, + const base::Closure& read_called, const base::Closure& write_called, const base::Closure& drop_called, const base::Closure& read_metadata_called, const base::Closure& read_all_metadata_called, const base::Closure& dtor_called) - : read_called_(read_called), + : init_called_(init_called), + read_called_(read_called), write_called_(write_called), drop_called_(drop_called), read_metadata_called_(read_metadata_called), @@ -36,6 +38,10 @@ class MockAttachmentStore : public AttachmentStoreBase { ~MockAttachmentStore() override { dtor_called_.Run(); } + void Init(const InitCallback& callback) override { + init_called_.Run(); + } + void Read(const AttachmentIdList& ids, const ReadCallback& callback) override { read_called_.Run(); @@ -60,6 +66,7 @@ class MockAttachmentStore : public AttachmentStoreBase { read_all_metadata_called_.Run(); } + base::Closure init_called_; base::Closure read_called_; base::Closure write_called_; base::Closure drop_called_; @@ -73,7 +80,8 @@ class MockAttachmentStore : public AttachmentStoreBase { class AttachmentStoreHandleTest : public testing::Test { protected: AttachmentStoreHandleTest() - : read_call_count_(0), + : init_call_count_(0), + read_call_count_(0), write_call_count_(0), drop_call_count_(0), read_metadata_call_count_(0), @@ -82,6 +90,8 @@ class AttachmentStoreHandleTest : public testing::Test { virtual void SetUp() { scoped_ptr<AttachmentStoreBase> backend(new MockAttachmentStore( + base::Bind(&AttachmentStoreHandleTest::InitCalled, + base::Unretained(this)), base::Bind(&AttachmentStoreHandleTest::ReadCalled, base::Unretained(this)), base::Bind(&AttachmentStoreHandleTest::WriteCalled, @@ -113,6 +123,8 @@ class AttachmentStoreHandleTest : public testing::Test { NOTREACHED(); } + void InitCalled() { ++init_call_count_; } + void ReadCalled() { ++read_call_count_; } void WriteCalled() { ++write_call_count_; } @@ -132,6 +144,7 @@ class AttachmentStoreHandleTest : public testing::Test { base::MessageLoop message_loop_; scoped_refptr<AttachmentStoreHandle> attachment_store_handle_; + int init_call_count_; int read_call_count_; int write_call_count_; int drop_call_count_; @@ -145,6 +158,12 @@ TEST_F(AttachmentStoreHandleTest, MethodsCalled) { AttachmentIdList ids; AttachmentList attachments; + attachment_store_handle_->Init( + base::Bind(&AttachmentStoreHandleTest::DoneWithResult)); + EXPECT_EQ(init_call_count_, 0); + RunMessageLoop(); + EXPECT_EQ(init_call_count_, 1); + attachment_store_handle_->Read( ids, base::Bind(&AttachmentStoreHandleTest::ReadDone)); EXPECT_EQ(read_call_count_, 0); diff --git a/sync/internal_api/attachments/in_memory_attachment_store.cc b/sync/internal_api/attachments/in_memory_attachment_store.cc index 6dbc4fa..f5000c7 100644 --- a/sync/internal_api/attachments/in_memory_attachment_store.cc +++ b/sync/internal_api/attachments/in_memory_attachment_store.cc @@ -21,6 +21,11 @@ InMemoryAttachmentStore::InMemoryAttachmentStore( InMemoryAttachmentStore::~InMemoryAttachmentStore() { } +void InMemoryAttachmentStore::Init(const InitCallback& callback) { + DCHECK(CalledOnValidThread()); + callback_task_runner_->PostTask(FROM_HERE, base::Bind(callback, SUCCESS)); +} + void InMemoryAttachmentStore::Read(const AttachmentIdList& ids, const ReadCallback& callback) { DCHECK(CalledOnValidThread()); diff --git a/sync/internal_api/attachments/on_disk_attachment_store.cc b/sync/internal_api/attachments/on_disk_attachment_store.cc index 76f96bc..16fa0c0 100644 --- a/sync/internal_api/attachments/on_disk_attachment_store.cc +++ b/sync/internal_api/attachments/on_disk_attachment_store.cc @@ -83,33 +83,47 @@ leveldb::Status WriteStoreMetadata( } // namespace OnDiskAttachmentStore::OnDiskAttachmentStore( - const scoped_refptr<base::SequencedTaskRunner>& callback_task_runner) - : callback_task_runner_(callback_task_runner) { + const scoped_refptr<base::SequencedTaskRunner>& callback_task_runner, + const base::FilePath& path) + : callback_task_runner_(callback_task_runner), path_(path) { } OnDiskAttachmentStore::~OnDiskAttachmentStore() { } +void OnDiskAttachmentStore::Init(const InitCallback& callback) { + DCHECK(CalledOnValidThread()); + Result result_code = OpenOrCreate(path_); + callback_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result_code)); +} + void OnDiskAttachmentStore::Read(const AttachmentIdList& ids, const ReadCallback& callback) { DCHECK(CalledOnValidThread()); - DCHECK(db_); scoped_ptr<AttachmentMap> result_map(new AttachmentMap()); scoped_ptr<AttachmentIdList> unavailable_attachments(new AttachmentIdList()); - AttachmentIdList::const_iterator iter = ids.begin(); - const AttachmentIdList::const_iterator end = ids.end(); - for (; iter != end; ++iter) { - scoped_ptr<Attachment> attachment = ReadSingleAttachment(*iter); - if (attachment) { - result_map->insert(std::make_pair(*iter, *attachment)); - } else { - unavailable_attachments->push_back(*iter); + Result result_code = STORE_INITIALIZATION_FAILED; + + if (db_) { + result_code = SUCCESS; + AttachmentIdList::const_iterator iter = ids.begin(); + const AttachmentIdList::const_iterator end = ids.end(); + for (; iter != end; ++iter) { + scoped_ptr<Attachment> attachment; + attachment = ReadSingleAttachment(*iter); + if (attachment) { + result_map->insert(std::make_pair(*iter, *attachment)); + } else { + unavailable_attachments->push_back(*iter); + } } + result_code = + unavailable_attachments->empty() ? SUCCESS : UNSPECIFIED_ERROR; + } else { + *unavailable_attachments = ids; } - Result result_code = - unavailable_attachments->empty() ? SUCCESS : UNSPECIFIED_ERROR; callback_task_runner_->PostTask( FROM_HERE, base::Bind(callback, @@ -121,14 +135,16 @@ void OnDiskAttachmentStore::Read(const AttachmentIdList& ids, void OnDiskAttachmentStore::Write(const AttachmentList& attachments, const WriteCallback& callback) { DCHECK(CalledOnValidThread()); - DCHECK(db_); - Result result_code = SUCCESS; - - AttachmentList::const_iterator iter = attachments.begin(); - const AttachmentList::const_iterator end = attachments.end(); - for (; iter != end; ++iter) { - if (!WriteSingleAttachment(*iter)) - result_code = UNSPECIFIED_ERROR; + Result result_code = STORE_INITIALIZATION_FAILED; + + if (db_) { + result_code = SUCCESS; + AttachmentList::const_iterator iter = attachments.begin(); + const AttachmentList::const_iterator end = attachments.end(); + for (; iter != end; ++iter) { + if (!WriteSingleAttachment(*iter)) + result_code = UNSPECIFIED_ERROR; + } } callback_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result_code)); } @@ -136,22 +152,24 @@ void OnDiskAttachmentStore::Write(const AttachmentList& attachments, void OnDiskAttachmentStore::Drop(const AttachmentIdList& ids, const DropCallback& callback) { DCHECK(CalledOnValidThread()); - DCHECK(db_); - Result result_code = SUCCESS; - leveldb::WriteOptions write_options = MakeWriteOptions(); - AttachmentIdList::const_iterator iter = ids.begin(); - const AttachmentIdList::const_iterator end = ids.end(); - for (; iter != end; ++iter) { - leveldb::WriteBatch write_batch; - write_batch.Delete(MakeDataKeyFromAttachmentId(*iter)); - write_batch.Delete(MakeMetadataKeyFromAttachmentId(*iter)); - - leveldb::Status status = db_->Write(write_options, &write_batch); - if (!status.ok()) { - // DB::Delete doesn't check if record exists, it returns ok just like - // AttachmentStore::Drop should. - DVLOG(1) << "DB::Write failed: status=" << status.ToString(); - result_code = UNSPECIFIED_ERROR; + Result result_code = STORE_INITIALIZATION_FAILED; + if (db_) { + result_code = SUCCESS; + leveldb::WriteOptions write_options = MakeWriteOptions(); + AttachmentIdList::const_iterator iter = ids.begin(); + const AttachmentIdList::const_iterator end = ids.end(); + for (; iter != end; ++iter) { + leveldb::WriteBatch write_batch; + write_batch.Delete(MakeDataKeyFromAttachmentId(*iter)); + write_batch.Delete(MakeMetadataKeyFromAttachmentId(*iter)); + + leveldb::Status status = db_->Write(write_options, &write_batch); + if (!status.ok()) { + // DB::Delete doesn't check if record exists, it returns ok just like + // AttachmentStore::Drop should. + DVLOG(1) << "DB::Write failed: status=" << status.ToString(); + result_code = UNSPECIFIED_ERROR; + } } } callback_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result_code)); @@ -171,7 +189,6 @@ void OnDiskAttachmentStore::ReadAllMetadata( AttachmentStore::Result OnDiskAttachmentStore::OpenOrCreate( const base::FilePath& path) { - DCHECK(CalledOnValidThread()); DCHECK(!db_); base::FilePath leveldb_path = path.Append(kLeveldbDirectory); diff --git a/sync/internal_api/attachments/on_disk_attachment_store_unittest.cc b/sync/internal_api/attachments/on_disk_attachment_store_unittest.cc index b33a983..620ff74 100644 --- a/sync/internal_api/attachments/on_disk_attachment_store_unittest.cc +++ b/sync/internal_api/attachments/on_disk_attachment_store_unittest.cc @@ -13,6 +13,7 @@ #include "base/time/time.h" #include "sync/internal_api/attachments/attachment_store_test_template.h" #include "sync/internal_api/attachments/proto/attachment_store.pb.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/leveldatabase/src/include/leveldb/db.h" #include "third_party/leveldatabase/src/include/leveldb/options.h" @@ -23,12 +24,9 @@ namespace syncer { namespace { -void AttachmentStoreCreated(scoped_refptr<AttachmentStore>* store_dest, - AttachmentStore::Result* result_dest, - const AttachmentStore::Result& result, - const scoped_refptr<AttachmentStore>& store) { +void AttachmentStoreCreated(AttachmentStore::Result* result_dest, + const AttachmentStore::Result& result) { *result_dest = result; - *store_dest = store; } } // namespace @@ -43,13 +41,12 @@ class OnDiskAttachmentStoreFactory { EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); scoped_refptr<AttachmentStore> store; AttachmentStore::Result result = AttachmentStore::UNSPECIFIED_ERROR; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store, &result)); + store = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &result)); base::RunLoop run_loop; run_loop.RunUntilIdle(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + EXPECT_EQ(AttachmentStore::SUCCESS, result); return store; } @@ -77,10 +74,12 @@ class OnDiskAttachmentStoreSpecificTest : public testing::Test { void CopyResultAttachments( AttachmentStore::Result* destination_result, + AttachmentIdList* destination_failed_attachment_ids, const AttachmentStore::Result& source_result, scoped_ptr<AttachmentMap> source_attachments, scoped_ptr<AttachmentIdList> source_failed_attachment_ids) { CopyResult(destination_result, source_result); + *destination_failed_attachment_ids = *source_failed_attachment_ids; } scoped_ptr<leveldb::DB> OpenLevelDB(const base::FilePath& path) { @@ -144,12 +143,11 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, CloseAndReopen) { AttachmentStore::Result result; result = AttachmentStore::UNSPECIFIED_ERROR; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &result)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + EXPECT_EQ(AttachmentStore::SUCCESS, result); result = AttachmentStore::UNSPECIFIED_ERROR; std::string some_data = "data"; @@ -162,28 +160,28 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, CloseAndReopen) { base::Unretained(this), &result)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + EXPECT_EQ(AttachmentStore::SUCCESS, result); - // Close attachment store. + // Close and reopen attachment store. store_ = nullptr; result = AttachmentStore::UNSPECIFIED_ERROR; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &result)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + EXPECT_EQ(AttachmentStore::SUCCESS, result); result = AttachmentStore::UNSPECIFIED_ERROR; AttachmentIdList attachment_ids; attachment_ids.push_back(attachment.GetId()); + AttachmentIdList failed_attachment_ids; store_->Read( attachment_ids, base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResultAttachments, - base::Unretained(this), - &result)); + base::Unretained(this), &result, &failed_attachment_ids)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + EXPECT_EQ(AttachmentStore::SUCCESS, result); + EXPECT_TRUE(failed_attachment_ids.empty()); } // Ensure loading corrupt attachment store fails. @@ -200,13 +198,11 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, FailToOpen) { current_file_content.size()); AttachmentStore::Result result = AttachmentStore::SUCCESS; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &result)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); - EXPECT_EQ(store_.get(), nullptr); + EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, result); } // Ensure that attachment store works correctly when store metadata is missing, @@ -221,12 +217,11 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, StoreMetadata) { OpenLevelDB(db_path); // Open database with AttachmentStore. AttachmentStore::Result result = AttachmentStore::UNSPECIFIED_ERROR; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &result)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + EXPECT_EQ(AttachmentStore::SUCCESS, result); // Close AttachmentStore so that test can check content. store_ = nullptr; RunLoop(); @@ -235,7 +230,7 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, StoreMetadata) { std::string data = ReadStoreMetadataRecord(db_path); attachment_store_pb::StoreMetadata metadata; EXPECT_TRUE(metadata.ParseFromString(data)); - EXPECT_EQ(metadata.schema_version(), 1); + EXPECT_EQ(1, metadata.schema_version()); // Set unknown future schema version. metadata.set_schema_version(2); @@ -244,26 +239,22 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, StoreMetadata) { // AttachmentStore should fail to load. result = AttachmentStore::SUCCESS; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &result)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); - EXPECT_EQ(store_.get(), nullptr); + EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, result); // Write garbage into metadata record. UpdateStoreMetadataRecord(db_path, "abra.cadabra"); // AttachmentStore should fail to load. result = AttachmentStore::SUCCESS; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &result)); RunLoop(); - EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); - EXPECT_EQ(store_.get(), nullptr); + EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, result); } // Ensure that attachment store correctly maintains metadata records for @@ -274,15 +265,13 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, RecordMetadata) { temp_dir_.path().Append(FILE_PATH_LITERAL("leveldb")); // Create attachment store. - AttachmentStore::Result result = AttachmentStore::UNSPECIFIED_ERROR; - AttachmentStore::CreateOnDiskStore( - temp_dir_.path(), - base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); - RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + AttachmentStore::Result create_result = AttachmentStore::UNSPECIFIED_ERROR; + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &create_result)); // Write two attachments. + AttachmentStore::Result write_result = AttachmentStore::UNSPECIFIED_ERROR; std::string some_data; AttachmentList attachments; some_data = "data1"; @@ -293,22 +282,20 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, RecordMetadata) { Attachment::Create(base::RefCountedString::TakeString(&some_data))); store_->Write(attachments, base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResult, - base::Unretained(this), - &result)); - RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + base::Unretained(this), &write_result)); // Delete one of written attachments. + AttachmentStore::Result drop_result = AttachmentStore::UNSPECIFIED_ERROR; AttachmentIdList attachment_ids; attachment_ids.push_back(attachments[0].GetId()); store_->Drop(attachment_ids, base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResult, - base::Unretained(this), - &result)); - RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + base::Unretained(this), &drop_result)); store_ = nullptr; RunLoop(); + EXPECT_EQ(AttachmentStore::SUCCESS, create_result); + EXPECT_EQ(AttachmentStore::SUCCESS, write_result); + EXPECT_EQ(AttachmentStore::SUCCESS, drop_result); // Verify that attachment store contains only records for second attachment. VerifyAttachmentRecordsPresent(db_path, attachments[0].GetId(), false); @@ -320,14 +307,13 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, MismatchedCrc) { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); // Create attachment store. - AttachmentStore::Result result = AttachmentStore::UNSPECIFIED_ERROR; - AttachmentStore::CreateOnDiskStore( + AttachmentStore::Result create_result = AttachmentStore::UNSPECIFIED_ERROR; + store_ = AttachmentStore::CreateOnDiskStore( temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), - base::Bind(&AttachmentStoreCreated, &store_, &result)); - RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + base::Bind(&AttachmentStoreCreated, &create_result)); // Write attachment with incorrect crc32c. + AttachmentStore::Result write_result = AttachmentStore::UNSPECIFIED_ERROR; const uint32_t intentionally_wrong_crc32c = 0; std::string some_data("data1"); Attachment attachment = Attachment::CreateFromParts( @@ -337,19 +323,78 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, MismatchedCrc) { attachments.push_back(attachment); store_->Write(attachments, base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResult, - base::Unretained(this), &result)); - RunLoop(); - EXPECT_EQ(result, AttachmentStore::SUCCESS); + base::Unretained(this), &write_result)); // Read attachment. + AttachmentStore::Result read_result = AttachmentStore::UNSPECIFIED_ERROR; AttachmentIdList attachment_ids; attachment_ids.push_back(attachment.GetId()); + AttachmentIdList failed_attachment_ids; + store_->Read( + attachment_ids, + base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResultAttachments, + base::Unretained(this), &read_result, &failed_attachment_ids)); + RunLoop(); + EXPECT_EQ(AttachmentStore::SUCCESS, create_result); + EXPECT_EQ(AttachmentStore::SUCCESS, write_result); + EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, read_result); + EXPECT_THAT(failed_attachment_ids, testing::ElementsAre(attachment.GetId())); +} + +// Ensure that after store initialization failure ReadWrite/Drop operations fail +// with correct error. +TEST_F(OnDiskAttachmentStoreSpecificTest, OpsAfterInitializationFailed) { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + base::FilePath db_path = + temp_dir_.path().Append(FILE_PATH_LITERAL("leveldb")); + base::CreateDirectory(db_path); + + // To simulate corrupt database write empty CURRENT file. + std::string current_file_content = ""; + base::WriteFile(db_path.Append(FILE_PATH_LITERAL("CURRENT")), + current_file_content.c_str(), current_file_content.size()); + + AttachmentStore::Result create_result = AttachmentStore::SUCCESS; + store_ = AttachmentStore::CreateOnDiskStore( + temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(), + base::Bind(&AttachmentStoreCreated, &create_result)); + + // Reading from uninitialized store should result in + // STORE_INITIALIZATION_FAILED. + AttachmentStore::Result read_result = AttachmentStore::SUCCESS; + AttachmentIdList attachment_ids; + attachment_ids.push_back(AttachmentId::Create()); + AttachmentIdList failed_attachment_ids; store_->Read( attachment_ids, base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResultAttachments, - base::Unretained(this), &result)); + base::Unretained(this), &read_result, &failed_attachment_ids)); + + // Dropping from uninitialized store should result in + // STORE_INITIALIZATION_FAILED. + AttachmentStore::Result drop_result = AttachmentStore::SUCCESS; + store_->Drop(attachment_ids, + base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResult, + base::Unretained(this), &drop_result)); + + // Writing to uninitialized store should result in + // STORE_INITIALIZATION_FAILED. + AttachmentStore::Result write_result = AttachmentStore::SUCCESS; + std::string some_data; + AttachmentList attachments; + some_data = "data1"; + attachments.push_back( + Attachment::Create(base::RefCountedString::TakeString(&some_data))); + store_->Write(attachments, + base::Bind(&OnDiskAttachmentStoreSpecificTest::CopyResult, + base::Unretained(this), &write_result)); + RunLoop(); - EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); + EXPECT_EQ(AttachmentStore::UNSPECIFIED_ERROR, create_result); + EXPECT_EQ(AttachmentStore::STORE_INITIALIZATION_FAILED, read_result); + EXPECT_THAT(failed_attachment_ids, testing::ElementsAre(attachment_ids[0])); + EXPECT_EQ(AttachmentStore::STORE_INITIALIZATION_FAILED, drop_result); + EXPECT_EQ(AttachmentStore::STORE_INITIALIZATION_FAILED, write_result); } } // namespace syncer |