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 |