| Index: sync/internal_api/attachments/on_disk_attachment_store_unittest.cc
|
| 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 3479b80f182bd35ededbe14c86315a482ba105a1..ded5f0a2ef2a3b029c62e778d570e192f86fb8eb 100644
|
| --- a/sync/internal_api/attachments/on_disk_attachment_store_unittest.cc
|
| +++ b/sync/internal_api/attachments/on_disk_attachment_store_unittest.cc
|
| @@ -12,7 +12,12 @@
|
| #include "base/thread_task_runner_handle.h"
|
| #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/gtest/include/gtest/gtest.h"
|
| +#include "third_party/leveldatabase/src/include/leveldb/db.h"
|
| +#include "third_party/leveldatabase/src/include/leveldb/options.h"
|
| +#include "third_party/leveldatabase/src/include/leveldb/slice.h"
|
| +#include "third_party/leveldatabase/src/include/leveldb/status.h"
|
|
|
| namespace syncer {
|
|
|
| @@ -78,6 +83,32 @@ class OnDiskAttachmentStoreSpecificTest : public testing::Test {
|
| CopyResult(destination_result, source_result);
|
| }
|
|
|
| + scoped_ptr<leveldb::DB> OpenLevelDB(const base::FilePath& path) {
|
| + leveldb::DB* db;
|
| + leveldb::Options options;
|
| + options.create_if_missing = true;
|
| + leveldb::Status s = leveldb::DB::Open(options, path.AsUTF8Unsafe(), &db);
|
| + EXPECT_TRUE(s.ok());
|
| + return make_scoped_ptr(db);
|
| + }
|
| +
|
| + void UpdateStoreMetadataRecord(const base::FilePath& path,
|
| + const std::string& content) {
|
| + scoped_ptr<leveldb::DB> db = OpenLevelDB(path);
|
| + leveldb::Status s =
|
| + db->Put(leveldb::WriteOptions(), "database-metadata", content);
|
| + EXPECT_TRUE(s.ok());
|
| + }
|
| +
|
| + std::string ReadStoreMetadataRecord(const base::FilePath& path) {
|
| + scoped_ptr<leveldb::DB> db = OpenLevelDB(path);
|
| + std::string content;
|
| + leveldb::Status s =
|
| + db->Get(leveldb::ReadOptions(), "database-metadata", &content);
|
| + EXPECT_TRUE(s.ok());
|
| + return content;
|
| + }
|
| +
|
| void RunLoop() {
|
| base::RunLoop run_loop;
|
| run_loop.RunUntilIdle();
|
| @@ -140,8 +171,8 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, FailToOpen) {
|
| temp_dir_.path().Append(FILE_PATH_LITERAL("leveldb"));
|
| base::CreateDirectory(db_path);
|
|
|
| - // To simulate corrupt database write garbage to CURRENT file.
|
| - std::string current_file_content = "abra.cadabra";
|
| + // 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());
|
| @@ -156,4 +187,61 @@ TEST_F(OnDiskAttachmentStoreSpecificTest, FailToOpen) {
|
| EXPECT_EQ(store_.get(), nullptr);
|
| }
|
|
|
| +// Ensure that attachment store works correctly when store metadata is missing,
|
| +// corrupt or has unknown schema version.
|
| +TEST_F(OnDiskAttachmentStoreSpecificTest, StoreMetadata) {
|
| + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| + base::FilePath db_path =
|
| + temp_dir_.path().Append(FILE_PATH_LITERAL("leveldb"));
|
| + base::CreateDirectory(db_path);
|
| +
|
| + // Create and close empty database.
|
| + 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));
|
| + RunLoop();
|
| + EXPECT_EQ(result, AttachmentStore::SUCCESS);
|
| + // Close AttachmentStore so that test can check content.
|
| + store_ = nullptr;
|
| + RunLoop();
|
| +
|
| + // AttachmentStore should create metadata record.
|
| + std::string data = ReadStoreMetadataRecord(db_path);
|
| + attachment_store_pb::AttachmentStoreMetadata metadata;
|
| + EXPECT_TRUE(metadata.ParseFromString(data));
|
| + EXPECT_EQ(metadata.schema_version(), 1);
|
| +
|
| + // Set unknown future schema version.
|
| + metadata.set_schema_version(2);
|
| + data = metadata.SerializeAsString();
|
| + UpdateStoreMetadataRecord(db_path, data);
|
| +
|
| + // AttachmentStore should fail to load.
|
| + result = AttachmentStore::SUCCESS;
|
| + AttachmentStore::CreateOnDiskStore(
|
| + temp_dir_.path(),
|
| + base::ThreadTaskRunnerHandle::Get(),
|
| + base::Bind(&AttachmentStoreCreated, &store_, &result));
|
| + RunLoop();
|
| + EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR);
|
| + EXPECT_EQ(store_.get(), nullptr);
|
| +
|
| + // 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));
|
| + RunLoop();
|
| + EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR);
|
| + EXPECT_EQ(store_.get(), nullptr);
|
| +}
|
| +
|
| } // namespace syncer
|
|
|