Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Unified Diff: chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc

Issue 18591004: [SyncFS] Implement MetadataDatabase initialization (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: +test verification Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e0b8c000516c8fbd5fb6c1e01a0a03e8f8d007f4
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
@@ -0,0 +1,316 @@
+// Copyright 2013 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 "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
+
+#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/sync_file_system/drive_backend/metadata_database.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/write_batch.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+namespace {
+
+const int64 kInitialChangeID = 1234;
+const char kSyncRootFolderID[] = "sync_root_folder_id";
+
+template <typename Value>
+bool AreEquivalentProtobuf(const Value& left, const Value& right) {
kinuko 2013/07/04 15:59:11 AreEquivalentProtobuf's' (for all AreEquivalentFoo
tzik 2013/07/05 07:42:28 Done.
+ std::string serialized_left;
+ std::string serialized_right;
+ left.SerializeToString(&serialized_left);
+ right.SerializeToString(&serialized_right);
+ return serialized_left == serialized_right;
+}
+
+void SyncStatusResultCallback(SyncStatusCode* status_out,
+ SyncStatusCode status) {
+ EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
+ *status_out = status;
+}
+
+// Returns true if given two std::map<Key, protobuf*> is equivalent under '=='.
+template <typename Container>
+bool AreEquivalentPtrMap(const Container& left, const Container& right) {
+ if (left.size() != right.size())
+ return false;
+
+ typedef typename Container::const_iterator const_iterator;
+ const_iterator left_itr = left.begin();
+ const_iterator right_itr = right.begin();
+
+ while (left_itr != left.end()) {
+ if (left_itr->first != right_itr->first)
+ return false;
+ if (!AreEquivalentProtobuf(*left_itr->second, *right_itr->second))
+ return false;
+
+ ++left_itr;
+ ++right_itr;
+ }
+ return true;
+}
+
+// Returns true if given two std::set<protobuf*> is equivalent under '=='.
+template <typename Container>
+bool AreEquivalentPtrSet(const Container& left, const Container& right) {
+ if (left.size() != right.size())
+ return false;
+
+ typedef typename Container::const_iterator const_iterator;
+ const_iterator left_itr = left.begin();
+ const_iterator right_itr = right.begin();
+ while (left_itr != left.end()) {
+ if (!AreEquivalentProtobuf(**left_itr, **right_itr))
+ return false;
+ ++left_itr;
+ ++right_itr;
+ }
+ return true;
+}
+
+// Returns true if given two std::map<Key, std::set<Value*> > is equivalent
+// under '=='.
+template <typename Container>
+bool AreEquivalentPtrSetMap(const Container& left, const Container& right) {
+ if (left.size() != right.size())
+ return false;
+
+ typedef typename Container::const_iterator const_iterator;
+ const_iterator left_itr = left.begin();
+ const_iterator right_itr = right.begin();
+
+ while (left_itr != left.end()) {
+ if (left_itr->first != right_itr->first)
+ return false;
+ if (!AreEquivalentPtrSet(left_itr->second, right_itr->second))
+ return false;
+ ++left_itr;
+ ++right_itr;
+ }
+ return true;
+}
+
+} // namespace
+
+class SyncFS_MetadataDatabaseTest : public testing::Test {
kinuko 2013/07/04 15:59:11 I'm slightly not sure about this naming. Does thi
tzik 2013/07/05 07:42:28 It doesn't conflict, but I feel a bit uneasy to pu
kinuko 2013/07/08 04:18:56 We're already adding generic test names, if we rea
+ public:
+ SyncFS_MetadataDatabaseTest()
+ : next_file_id_number_(1) {
+ }
+
+ virtual ~SyncFS_MetadataDatabaseTest() {
+ }
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
+ }
+
+ virtual void TearDown() OVERRIDE {
+ DropDatabase();
+ }
+
+ protected:
+ std::string GenerateFileID() {
+ return "file_id_" + base::Int64ToString(next_file_id_number_++);
+ }
+
+ SyncStatusCode InitializeDatabase() {
+ SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+ metadata_database_.reset(new MetadataDatabase(
+ base::MessageLoopProxy::current()));
+ metadata_database_->Initialize(
+ database_dir_.path(),
+ base::Bind(&SyncStatusResultCallback, &status));
+ message_loop_.RunUntilIdle();
+ return status;
+ }
+
+ void DropDatabase() {
+ metadata_database_.reset();
+ message_loop_.RunUntilIdle();
+ }
+
+ MetadataDatabase* metadata_database() {
+ return metadata_database_.get();
+ }
+
+ leveldb::DB* db() {
+ if (!metadata_database_)
+ return NULL;
+ return metadata_database_->db_.get();
+ }
+
+ scoped_ptr<leveldb::DB> OpenDB() {
+ bool created = false;
+ SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+ scoped_ptr<leveldb::DB> db = MetadataDatabase::OpenDatabase(
+ database_dir_.path(), &status, &created);
+ EXPECT_EQ(status, SYNC_STATUS_OK);
+ return db.Pass();
+ }
+
+ void SetUpServiceMetadata(leveldb::DB* db) {
+ ServiceMetadata service_metadata;
+ service_metadata.set_largest_change_id(kInitialChangeID);
+ service_metadata.set_sync_root_folder_id(kSyncRootFolderID);
+ std::string value;
+ ASSERT_TRUE(service_metadata.SerializeToString(&value));
+ db->Put(leveldb::WriteOptions(), "SERVICE", value);
+ }
+
+ DriveFileMetadata CreateSyncRoot() {
+ DriveFileMetadata metadata;
+ metadata.set_file_id(kSyncRootFolderID);
+ metadata.set_parent_folder_id(std::string());
+ metadata.mutable_synced_details()->set_title("Chrome Syncable FileSystem");
+ metadata.mutable_synced_details()->set_kind(KIND_FOLDER);
+ metadata.set_active(true);
+ return metadata;
+ }
+
+ DriveFileMetadata CreateUnknownFile(const std::string& app_id,
+ const std::string& parent_folder_id) {
+ DriveFileMetadata metadata;
+ metadata.set_file_id(GenerateFileID());
+ metadata.set_parent_folder_id(parent_folder_id);
+ metadata.set_app_id(app_id);
+ metadata.set_is_app_root(parent_folder_id == kSyncRootFolderID);
+ return metadata;
+ }
+
+ DriveFileMetadata CreateFile(const std::string& app_id,
+ const std::string& parent_folder_id,
+ const std::string& title) {
+ DriveFileMetadata file(CreateUnknownFile(app_id, parent_folder_id));
+ file.mutable_synced_details()->add_parent_folder_id(parent_folder_id);
+ file.mutable_synced_details()->set_title(title);
+ file.mutable_synced_details()->set_kind(KIND_FILE);
+ file.set_active(true);
+ file.set_dirty(false);
+ return file;
+ }
+
+ DriveFileMetadata CreateFolder(const std::string& app_id,
+ const std::string& parent_folder_id,
+ const std::string& title) {
+ DriveFileMetadata folder(CreateUnknownFile(app_id, parent_folder_id));
+ folder.mutable_synced_details()->add_parent_folder_id(parent_folder_id);
+ folder.mutable_synced_details()->set_title(title);
+ folder.mutable_synced_details()->set_kind(KIND_FOLDER);
+ folder.set_active(true);
+ folder.set_dirty(false);
+ return folder;
+ }
+
+ DriveFileMetadata CreateUnsupportedFile(const std::string& app_id,
+ const std::string& parent_folder_id,
+ const std::string& title) {
+ DriveFileMetadata file(CreateUnknownFile(app_id, parent_folder_id));
+ file.mutable_synced_details()->add_parent_folder_id(parent_folder_id);
+ file.mutable_synced_details()->set_title(title);
+ file.mutable_synced_details()->set_kind(KIND_UNSUPPORTED);
+ file.set_active(false);
+ file.set_dirty(false);
+ return file;
+ }
+
+ leveldb::Status PutFileToDB(leveldb::DB* db, const DriveFileMetadata& file) {
+ std::string key = "FILE: " + file.file_id();
+ std::string value;
+ file.SerializeToString(&value);
+ return db->Put(leveldb::WriteOptions(), key, value);
+ }
+
+ void VerifyReloadConsistency() {
kinuko 2013/07/04 15:59:11 Is it same if we save all internal maps of metadat
+ MetadataDatabase::InitializeInfo info;
+
+ ASSERT_EQ(SYNC_STATUS_OK,
+ MetadataDatabase::ReadDatabaseContents(
+ metadata_database_->db_.get(), &info));
+
+ leveldb::WriteBatch batch;
+ ASSERT_EQ(SYNC_STATUS_OK,
+ MetadataDatabase::ConstructDataStructure(&info, &batch));
+
+ EXPECT_TRUE(AreEquivalentPtrMap(info.file_by_file_id,
+ metadata_database_->file_by_file_id_));
+ EXPECT_TRUE(AreEquivalentPtrSetMap(info.files_by_parent,
+ metadata_database_->files_by_parent_));
+ EXPECT_TRUE(AreEquivalentPtrMap(info.app_root_by_app_id,
+ metadata_database_->app_root_by_app_id_));
+ EXPECT_TRUE(AreEquivalentPtrMap(
+ info.active_file_by_parent_and_title,
+ metadata_database_->active_file_by_parent_and_title_));
+ }
+
+ void VerifyMetadataExists(const DriveFileMetadata& file) {
+ DriveFileMetadata file_in_metadata_db;
+ ASSERT_TRUE(metadata_database()->FindFileByFileID(
+ file.file_id(), &file_in_metadata_db));
+ EXPECT_TRUE(AreEquivalentProtobuf(file, file_in_metadata_db));
+ }
+
+ private:
+ base::ScopedTempDir database_dir_;
+ base::MessageLoop message_loop_;
+
+ scoped_ptr<MetadataDatabase> metadata_database_;
+
+ int64 next_file_id_number_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncFS_MetadataDatabaseTest);
+};
+
+TEST_F(SyncFS_MetadataDatabaseTest, InitializationTest_Empty) {
+ EXPECT_EQ(SYNC_STATUS_OK, InitializeDatabase());
+ VerifyReloadConsistency();
+ DropDatabase();
+ EXPECT_EQ(SYNC_STATUS_OK, InitializeDatabase());
+}
+
+TEST_F(SyncFS_MetadataDatabaseTest, InitializationTest_SimpleTree) {
+ std::string app_id = "app_id";
+ DriveFileMetadata sync_root(CreateSyncRoot());
+ DriveFileMetadata app_root(CreateFolder(app_id, kSyncRootFolderID, app_id));
+ DriveFileMetadata file(CreateFile(app_id, app_root.file_id(), "file"));
+ DriveFileMetadata folder(CreateFolder(app_id, app_root.file_id(), "folder"));
+ DriveFileMetadata file_in_folder(
+ CreateFile(app_id, folder.file_id(), "file_in_folder"));
+ DriveFileMetadata orphaned(CreateUnknownFile(std::string(), "root"));
+
+ {
+ scoped_ptr<leveldb::DB> db = OpenDB();
+ ASSERT_TRUE(db);
+ db->Put(leveldb::WriteOptions(), "VERSION", base::Int64ToString(3));
+ SetUpServiceMetadata(db.get());
+
+ EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), file_in_folder).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), orphaned).ok());
+ }
+
+ EXPECT_EQ(SYNC_STATUS_OK, InitializeDatabase());
+ VerifyReloadConsistency();
+
+ VerifyMetadataExists(sync_root);
+ VerifyMetadataExists(app_root);
+ VerifyMetadataExists(file);
+ VerifyMetadataExists(folder);
+ VerifyMetadataExists(file_in_folder);
+ EXPECT_FALSE(metadata_database()->FindFileByFileID(orphaned.file_id(), NULL));
+}
+
+} // namespace drive_backend
+} // namespace sync_file_system

Powered by Google App Engine
This is Rietveld 408576698