Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/files/scoped_temp_dir.h" | |
| 9 #include "base/message_loop/message_loop.h" | |
| 10 #include "base/message_loop/message_loop_proxy.h" | |
| 11 #include "base/strings/string_number_conversions.h" | |
| 12 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | |
| 14 #include "third_party/leveldatabase/src/include/leveldb/db.h" | |
| 15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | |
| 16 | |
| 17 namespace sync_file_system { | |
| 18 namespace drive_backend { | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 const int64 kInitialChangeID = 1234; | |
| 23 const char kSyncRootFolderID[] = "sync_root_folder_id"; | |
| 24 | |
| 25 template <typename Value> | |
| 26 bool AreEquivalentProtobufs(const Value& left, const Value& right) { | |
| 27 std::string serialized_left; | |
| 28 std::string serialized_right; | |
| 29 left.SerializeToString(&serialized_left); | |
| 30 right.SerializeToString(&serialized_right); | |
| 31 return serialized_left == serialized_right; | |
| 32 } | |
| 33 | |
| 34 void SyncStatusResultCallback(SyncStatusCode* status_out, | |
| 35 SyncStatusCode status) { | |
| 36 EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out); | |
| 37 *status_out = status; | |
| 38 } | |
| 39 | |
| 40 void DatabaseCreateResultCallback(SyncStatusCode* status_out, | |
| 41 scoped_ptr<MetadataDatabase>* database_out, | |
| 42 SyncStatusCode status, | |
| 43 scoped_ptr<MetadataDatabase> database) { | |
| 44 EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out); | |
| 45 *status_out = status; | |
| 46 *database_out = database.Pass(); | |
| 47 } | |
| 48 | |
| 49 } // namespace | |
| 50 | |
| 51 class MetadataDatabaseTest : public testing::Test { | |
| 52 public: | |
| 53 MetadataDatabaseTest() : next_file_id_number_(1) {} | |
| 54 | |
| 55 virtual ~MetadataDatabaseTest() {} | |
| 56 | |
| 57 virtual void SetUp() OVERRIDE { | |
| 58 ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); | |
| 59 } | |
| 60 | |
| 61 virtual void TearDown() OVERRIDE { DropDatabase(); } | |
| 62 | |
| 63 protected: | |
| 64 std::string GenerateFileID() { | |
| 65 return "file_id_" + base::Int64ToString(next_file_id_number_++); | |
| 66 } | |
| 67 | |
| 68 SyncStatusCode InitializeDatabase() { | |
| 69 SyncStatusCode status = SYNC_STATUS_UNKNOWN; | |
| 70 MetadataDatabase::Create(base::MessageLoopProxy::current(), | |
| 71 database_dir_.path(), | |
| 72 base::Bind(&DatabaseCreateResultCallback, | |
| 73 &status, &metadata_database_)); | |
| 74 message_loop_.RunUntilIdle(); | |
| 75 return status; | |
| 76 } | |
| 77 | |
| 78 void DropDatabase() { | |
| 79 metadata_database_.reset(); | |
| 80 message_loop_.RunUntilIdle(); | |
| 81 } | |
| 82 | |
| 83 MetadataDatabase* metadata_database() { return metadata_database_.get(); } | |
| 84 | |
| 85 leveldb::DB* db() { | |
| 86 if (!metadata_database_) | |
| 87 return NULL; | |
| 88 return metadata_database_->db_.get(); | |
| 89 } | |
| 90 | |
| 91 scoped_ptr<leveldb::DB> OpenDB() { | |
| 92 leveldb::DB* db = NULL; | |
| 93 leveldb::Options options; | |
| 94 options.create_if_missing = true; | |
| 95 leveldb::Status status = | |
| 96 leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db); | |
| 97 EXPECT_TRUE(status.ok()); | |
| 98 return make_scoped_ptr(db); | |
| 99 } | |
| 100 | |
| 101 void SetUpServiceMetadata(leveldb::DB* db) { | |
| 102 ServiceMetadata service_metadata; | |
| 103 service_metadata.set_largest_change_id(kInitialChangeID); | |
| 104 service_metadata.set_sync_root_folder_id(kSyncRootFolderID); | |
| 105 std::string value; | |
| 106 ASSERT_TRUE(service_metadata.SerializeToString(&value)); | |
| 107 db->Put(leveldb::WriteOptions(), "SERVICE", value); | |
| 108 } | |
| 109 | |
| 110 DriveFileMetadata CreateSyncRoot() { | |
| 111 DriveFileMetadata metadata; | |
| 112 metadata.set_file_id(kSyncRootFolderID); | |
| 113 metadata.set_parent_folder_id(std::string()); | |
| 114 metadata.mutable_synced_details()->set_title("Chrome Syncable FileSystem"); | |
| 115 metadata.mutable_synced_details()->set_kind(KIND_FOLDER); | |
| 116 metadata.set_active(true); | |
|
kinuko
2013/07/08 04:18:56
nit: set_dirty(false) ?
tzik
2013/07/08 08:46:17
Done.
| |
| 117 return metadata; | |
| 118 } | |
| 119 | |
| 120 DriveFileMetadata CreateUnknownFile(const std::string& app_id, | |
| 121 const std::string& parent_folder_id) { | |
| 122 DriveFileMetadata metadata; | |
| 123 metadata.set_file_id(GenerateFileID()); | |
| 124 metadata.set_parent_folder_id(parent_folder_id); | |
| 125 metadata.set_app_id(app_id); | |
| 126 metadata.set_is_app_root(parent_folder_id == kSyncRootFolderID); | |
| 127 return metadata; | |
| 128 } | |
| 129 | |
| 130 DriveFileMetadata CreateFile(const std::string& app_id, | |
| 131 const std::string& parent_folder_id, | |
| 132 const std::string& title) { | |
| 133 DriveFileMetadata file(CreateUnknownFile(app_id, parent_folder_id)); | |
| 134 file.mutable_synced_details()->add_parent_folder_id(parent_folder_id); | |
| 135 file.mutable_synced_details()->set_title(title); | |
| 136 file.mutable_synced_details()->set_kind(KIND_FILE); | |
| 137 file.set_active(true); | |
| 138 file.set_dirty(false); | |
| 139 return file; | |
| 140 } | |
| 141 | |
| 142 DriveFileMetadata CreateFolder(const std::string& app_id, | |
| 143 const std::string& parent_folder_id, | |
| 144 const std::string& title) { | |
| 145 DriveFileMetadata folder(CreateUnknownFile(app_id, parent_folder_id)); | |
| 146 folder.mutable_synced_details()->add_parent_folder_id(parent_folder_id); | |
| 147 folder.mutable_synced_details()->set_title(title); | |
| 148 folder.mutable_synced_details()->set_kind(KIND_FOLDER); | |
| 149 folder.set_active(true); | |
| 150 folder.set_dirty(false); | |
| 151 return folder; | |
| 152 } | |
| 153 | |
| 154 DriveFileMetadata CreateUnsupportedFile(const std::string& app_id, | |
|
kinuko
2013/07/08 04:18:56
nit: not used?
tzik
2013/07/08 08:46:17
Done.
| |
| 155 const std::string& parent_folder_id, | |
| 156 const std::string& title) { | |
| 157 DriveFileMetadata file(CreateUnknownFile(app_id, parent_folder_id)); | |
| 158 file.mutable_synced_details()->add_parent_folder_id(parent_folder_id); | |
| 159 file.mutable_synced_details()->set_title(title); | |
| 160 file.mutable_synced_details()->set_kind(KIND_UNSUPPORTED); | |
| 161 file.set_active(false); | |
| 162 file.set_dirty(false); | |
| 163 return file; | |
| 164 } | |
| 165 | |
| 166 leveldb::Status PutFileToDB(leveldb::DB* db, const DriveFileMetadata& file) { | |
| 167 std::string key = "FILE: " + file.file_id(); | |
| 168 std::string value; | |
| 169 file.SerializeToString(&value); | |
| 170 return db->Put(leveldb::WriteOptions(), key, value); | |
| 171 } | |
| 172 | |
| 173 void VerifyMetadataExists(const DriveFileMetadata& file) { | |
| 174 DriveFileMetadata file_in_metadata_db; | |
| 175 ASSERT_TRUE(metadata_database()->FindFileByFileID( | |
| 176 file.file_id(), &file_in_metadata_db)); | |
| 177 EXPECT_TRUE(AreEquivalentProtobufs(file, file_in_metadata_db)); | |
| 178 } | |
| 179 | |
| 180 private: | |
| 181 base::ScopedTempDir database_dir_; | |
| 182 base::MessageLoop message_loop_; | |
| 183 | |
| 184 scoped_ptr<MetadataDatabase> metadata_database_; | |
| 185 | |
| 186 int64 next_file_id_number_; | |
| 187 | |
| 188 DISALLOW_COPY_AND_ASSIGN(MetadataDatabaseTest); | |
| 189 }; | |
| 190 | |
| 191 TEST_F(MetadataDatabaseTest, InitializationTest_Empty) { | |
| 192 EXPECT_EQ(SYNC_STATUS_OK, InitializeDatabase()); | |
| 193 DropDatabase(); | |
| 194 EXPECT_EQ(SYNC_STATUS_OK, InitializeDatabase()); | |
| 195 } | |
| 196 | |
| 197 TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) { | |
| 198 std::string app_id = "app_id"; | |
| 199 DriveFileMetadata sync_root(CreateSyncRoot()); | |
| 200 DriveFileMetadata app_root(CreateFolder(app_id, kSyncRootFolderID, app_id)); | |
| 201 DriveFileMetadata file(CreateFile(app_id, app_root.file_id(), "file")); | |
| 202 DriveFileMetadata folder(CreateFolder(app_id, app_root.file_id(), "folder")); | |
| 203 DriveFileMetadata file_in_folder( | |
| 204 CreateFile(app_id, folder.file_id(), "file_in_folder")); | |
| 205 DriveFileMetadata orphaned(CreateUnknownFile(std::string(), "root")); | |
| 206 | |
| 207 { | |
| 208 scoped_ptr<leveldb::DB> db = OpenDB(); | |
| 209 ASSERT_TRUE(db); | |
| 210 db->Put(leveldb::WriteOptions(), "VERSION", base::Int64ToString(3)); | |
| 211 SetUpServiceMetadata(db.get()); | |
| 212 | |
| 213 EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok()); | |
| 214 EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok()); | |
| 215 EXPECT_TRUE(PutFileToDB(db.get(), file).ok()); | |
| 216 EXPECT_TRUE(PutFileToDB(db.get(), folder).ok()); | |
| 217 EXPECT_TRUE(PutFileToDB(db.get(), file_in_folder).ok()); | |
| 218 EXPECT_TRUE(PutFileToDB(db.get(), orphaned).ok()); | |
| 219 } | |
| 220 | |
| 221 EXPECT_EQ(SYNC_STATUS_OK, InitializeDatabase()); | |
| 222 | |
| 223 VerifyMetadataExists(sync_root); | |
| 224 VerifyMetadataExists(app_root); | |
| 225 VerifyMetadataExists(file); | |
| 226 VerifyMetadataExists(folder); | |
| 227 VerifyMetadataExists(file_in_folder); | |
| 228 EXPECT_FALSE(metadata_database()->FindFileByFileID(orphaned.file_id(), NULL)); | |
| 229 } | |
| 230 | |
| 231 } // namespace drive_backend | |
| 232 } // namespace sync_file_system | |
| OLD | NEW |