metadata_database_unittest.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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/google_apis/drive_api_parser.h"
13#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "third_party/leveldatabase/src/include/leveldb/db.h"
16#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
17
18#define FPL(a) FILE_PATH_LITERAL(a)
19
20namespace sync_file_system {
21namespace drive_backend {
22
23typedef MetadataDatabase::FileSet FileSet;
24typedef MetadataDatabase::FileByFileID FileByFileID;
25typedef MetadataDatabase::FilesByParent FilesByParent;
26typedef MetadataDatabase::FileByParentAndTitle FileByParentAndTitle;
27typedef MetadataDatabase::FileByAppID FileByAppID;
28
29namespace {
30
31const int64 kInitialChangeID = 1234;
32const char kSyncRootFolderID[] = "sync_root_folder_id";
33
34void ExpectEquivalent(const DriveFileMetadata::Details* left,
35                      const DriveFileMetadata::Details* right) {
36  EXPECT_EQ(left->title(), right->title());
37  EXPECT_EQ(left->kind(), right->kind());
38  EXPECT_EQ(left->md5(), right->md5());
39  EXPECT_EQ(left->etag(), right->etag());
40  EXPECT_EQ(left->creation_time(), right->creation_time());
41  EXPECT_EQ(left->modification_time(), right->modification_time());
42  EXPECT_EQ(left->deleted(), right->deleted());
43  EXPECT_EQ(left->change_id(), right->change_id());
44}
45
46void ExpectEquivalent(const DriveFileMetadata* left,
47                      const DriveFileMetadata* right) {
48  EXPECT_EQ(left->file_id(), right->file_id());
49  EXPECT_EQ(left->parent_folder_id(), right->parent_folder_id());
50  EXPECT_EQ(left->app_id(), right->app_id());
51  EXPECT_EQ(left->is_app_root(), right->is_app_root());
52
53  {
54    SCOPED_TRACE("Expect equivalent synced_details.");
55    ExpectEquivalent(&left->synced_details(), &right->synced_details());
56  }
57
58  {
59    SCOPED_TRACE("Expect equivalent remote_details.");
60    ExpectEquivalent(&left->remote_details(), &right->remote_details());
61  }
62
63  EXPECT_EQ(left->dirty(), right->dirty());
64  EXPECT_EQ(left->active(), right->active());
65  EXPECT_EQ(left->needs_folder_listing(), right->needs_folder_listing());
66}
67
68template <typename Container>
69void ExpectEquivalentMaps(const Container& left, const Container& right);
70template <typename Key, typename Value, typename Compare>
71void ExpectEquivalent(const std::map<Key, Value, Compare>& left,
72                      const std::map<Key, Value, Compare>& right) {
73  ExpectEquivalentMaps(left, right);
74}
75
76template <typename Container>
77void ExpectEquivalentSets(const Container& left, const Container& right);
78template <typename Value, typename Compare>
79void ExpectEquivalent(const std::set<Value, Compare>& left,
80                      const std::set<Value, Compare>& right) {
81  return ExpectEquivalentSets(left, right);
82}
83
84template <typename Container>
85void ExpectEquivalentMaps(const Container& left, const Container& right) {
86  ASSERT_EQ(left.size(), right.size());
87
88  typedef typename Container::const_iterator const_iterator;
89  const_iterator left_itr = left.begin();
90  const_iterator right_itr = right.begin();
91  while (left_itr != left.end()) {
92    EXPECT_EQ(left_itr->first, right_itr->first);
93    ExpectEquivalent(left_itr->second, right_itr->second);
94    ++left_itr;
95    ++right_itr;
96  }
97}
98
99template <typename Container>
100void ExpectEquivalentSets(const Container& left, const Container& right) {
101  ASSERT_EQ(left.size(), right.size());
102
103  typedef typename Container::const_iterator const_iterator;
104  const_iterator left_itr = left.begin();
105  const_iterator right_itr = right.begin();
106  while (left_itr != left.end()) {
107    ExpectEquivalent(*left_itr, *right_itr);
108    ++left_itr;
109    ++right_itr;
110  }
111}
112
113void SyncStatusResultCallback(SyncStatusCode* status_out,
114                              SyncStatusCode status) {
115  EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
116  *status_out = status;
117}
118
119void DatabaseCreateResultCallback(SyncStatusCode* status_out,
120                                  scoped_ptr<MetadataDatabase>* database_out,
121                                  SyncStatusCode status,
122                                  scoped_ptr<MetadataDatabase> database) {
123  EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
124  *status_out = status;
125  *database_out = database.Pass();
126}
127
128}  // namespace
129
130class MetadataDatabaseTest : public testing::Test {
131 public:
132  MetadataDatabaseTest()
133      : next_change_id_(kInitialChangeID + 1),
134        next_file_id_number_(1),
135        next_md5_sequence_number_(1) {}
136
137  virtual ~MetadataDatabaseTest() {}
138
139  virtual void SetUp() OVERRIDE {
140    ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
141  }
142
143  virtual void TearDown() OVERRIDE { DropDatabase(); }
144
145 protected:
146  std::string GenerateFileID() {
147    return "file_id_" + base::Int64ToString(next_file_id_number_++);
148  }
149
150  SyncStatusCode InitializeMetadataDatabase() {
151    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
152    MetadataDatabase::Create(base::MessageLoopProxy::current(),
153                             database_dir_.path(),
154                             base::Bind(&DatabaseCreateResultCallback,
155                                        &status, &metadata_database_));
156    message_loop_.RunUntilIdle();
157    return status;
158  }
159
160  void DropDatabase() {
161    metadata_database_.reset();
162    message_loop_.RunUntilIdle();
163  }
164
165  MetadataDatabase* metadata_database() { return metadata_database_.get(); }
166
167  leveldb::DB* db() {
168    if (!metadata_database_)
169      return NULL;
170    return metadata_database_->db_.get();
171  }
172
173  scoped_ptr<leveldb::DB> InitializeLevelDB() {
174    leveldb::DB* db = NULL;
175    leveldb::Options options;
176    options.create_if_missing = true;
177    options.max_open_files = 0;  // Use minimum.
178    leveldb::Status status =
179        leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
180    EXPECT_TRUE(status.ok());
181
182    db->Put(leveldb::WriteOptions(), "VERSION", base::Int64ToString(3));
183    SetUpServiceMetadata(db);
184
185    return make_scoped_ptr(db);
186  }
187
188  void SetUpServiceMetadata(leveldb::DB* db) {
189    ServiceMetadata service_metadata;
190    service_metadata.set_largest_change_id(kInitialChangeID);
191    service_metadata.set_sync_root_folder_id(kSyncRootFolderID);
192    std::string value;
193    ASSERT_TRUE(service_metadata.SerializeToString(&value));
194    db->Put(leveldb::WriteOptions(), "SERVICE", value);
195  }
196
197  DriveFileMetadata CreateSyncRootMetadata() {
198    DriveFileMetadata sync_root;
199    sync_root.set_file_id(kSyncRootFolderID);
200    sync_root.set_parent_folder_id(std::string());
201    sync_root.mutable_synced_details()->set_title("Chrome Syncable FileSystem");
202    sync_root.mutable_synced_details()->set_kind(KIND_FOLDER);
203    sync_root.set_active(true);
204    sync_root.set_dirty(false);
205    return sync_root;
206  }
207
208  DriveFileMetadata CreateAppRootMetadata(const DriveFileMetadata& sync_root,
209                                          const std::string& app_id) {
210    DriveFileMetadata app_root(
211        CreateFolderMetadata(sync_root, app_id /* title */));
212    app_root.set_app_id(app_id);
213    app_root.set_is_app_root(true);
214    return app_root;
215  }
216
217  DriveFileMetadata CreateUnknownFileMetadata(const DriveFileMetadata& parent) {
218    DriveFileMetadata file;
219    file.set_file_id(GenerateFileID());
220    file.set_parent_folder_id(parent.file_id());
221    file.set_app_id(parent.app_id());
222    file.set_is_app_root(false);
223    return file;
224  }
225
226  DriveFileMetadata CreateFileMetadata(const DriveFileMetadata& parent,
227                                       const std::string& title) {
228    DriveFileMetadata file(CreateUnknownFileMetadata(parent));
229    file.mutable_synced_details()->add_parent_folder_id(parent.file_id());
230    file.mutable_synced_details()->set_title(title);
231    file.mutable_synced_details()->set_kind(KIND_FILE);
232    file.mutable_synced_details()->set_md5(
233        "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
234    file.set_active(true);
235    file.set_dirty(false);
236    return file;
237  }
238
239  DriveFileMetadata CreateFolderMetadata(const DriveFileMetadata& parent,
240                                         const std::string& title) {
241    DriveFileMetadata folder(CreateUnknownFileMetadata(parent));
242    folder.mutable_synced_details()->add_parent_folder_id(parent.file_id());
243    folder.mutable_synced_details()->set_title(title);
244    folder.mutable_synced_details()->set_kind(KIND_FOLDER);
245    folder.set_active(true);
246    folder.set_dirty(false);
247    return folder;
248  }
249
250  scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
251      const DriveFileMetadata& file) {
252    scoped_ptr<google_apis::ChangeResource> change(
253        new google_apis::ChangeResource);
254    change->set_change_id(file.remote_details().change_id());
255    change->set_file_id(file.file_id());
256    change->set_deleted(file.remote_details().deleted());
257    if (change->is_deleted())
258      return change.Pass();
259
260    scoped_ptr<google_apis::FileResource> file_resource(
261        new google_apis::FileResource);
262    ScopedVector<google_apis::ParentReference> parents;
263    for (int i = 0; i < file.remote_details().parent_folder_id_size(); ++i) {
264      scoped_ptr<google_apis::ParentReference> parent(
265          new google_apis::ParentReference);
266      parent->set_file_id(file.remote_details().parent_folder_id(i));
267      parents.push_back(parent.release());
268    }
269
270    file_resource->set_file_id(file.file_id());
271    file_resource->set_parents(&parents);
272    file_resource->set_title(file.remote_details().title());
273    if (file.remote_details().kind() == KIND_FOLDER)
274      file_resource->set_mime_type("application/vnd.google-apps.folder");
275    else if (file.remote_details().kind() == KIND_FILE)
276      file_resource->set_mime_type("text/plain");
277    else
278      file_resource->set_mime_type("application/vnd.google-apps.document");
279    file_resource->set_md5_checksum(file.remote_details().md5());
280    file_resource->set_etag(file.remote_details().etag());
281    file_resource->set_created_date(base::Time::FromInternalValue(
282        file.remote_details().creation_time()));
283    file_resource->set_modified_date(base::Time::FromInternalValue(
284        file.remote_details().modification_time()));
285
286    change->set_file(file_resource.Pass());
287    return change.Pass();
288  }
289
290  void ApplyRenameChangeToMetadata(const std::string& new_title,
291                                   DriveFileMetadata* file) {
292    DriveFileMetadata::Details* details = file->mutable_remote_details();
293    *details = file->synced_details();
294    details->set_title(new_title);
295    details->set_change_id(next_change_id_++);
296    file->set_dirty(true);
297  }
298
299  void ApplyReorganizeChangeToMetadata(const std::string& new_parent,
300                                       DriveFileMetadata* file) {
301    DriveFileMetadata::Details* details = file->mutable_remote_details();
302    *details = file->synced_details();
303    details->clear_parent_folder_id();
304    details->add_parent_folder_id(new_parent);
305    details->set_change_id(next_change_id_++);
306    file->set_dirty(true);
307  }
308
309  void ApplyContentChangeToMetadata(DriveFileMetadata* file) {
310    DriveFileMetadata::Details* details = file->mutable_remote_details();
311    *details = file->synced_details();
312    details->set_md5(
313        "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
314    details->set_change_id(next_change_id_++);
315    file->set_dirty(true);
316  }
317
318  void ApplyNoopChangeToMetadata(DriveFileMetadata* file) {
319    *file->mutable_remote_details() = file->synced_details();
320    file->mutable_remote_details()->set_change_id(next_change_id_++);
321    file->set_dirty(true);
322  }
323
324  void ApplyNewFileChangeToMetadata(DriveFileMetadata* file) {
325    *file->mutable_remote_details() = file->synced_details();
326    file->clear_synced_details();
327    file->mutable_remote_details()->set_change_id(next_change_id_++);
328    file->set_active(false);
329    file->set_dirty(true);
330  }
331
332  void PushToChangeList(scoped_ptr<google_apis::ChangeResource> change,
333                        ScopedVector<google_apis::ChangeResource>* changes) {
334    changes->push_back(change.release());
335  }
336
337  leveldb::Status PutFileToDB(leveldb::DB* db, const DriveFileMetadata& file) {
338    std::string key = "FILE: " + file.file_id();
339    std::string value;
340    file.SerializeToString(&value);
341    return db->Put(leveldb::WriteOptions(), key, value);
342  }
343
344  void VerifyReloadConsistency() {
345    scoped_ptr<MetadataDatabase> metadata_database_2;
346    ASSERT_EQ(SYNC_STATUS_OK,
347              MetadataDatabase::CreateForTesting(
348                  metadata_database_->db_.Pass(),
349                  &metadata_database_2));
350    metadata_database_->db_ = metadata_database_2->db_.Pass();
351
352    {
353      SCOPED_TRACE("Expect equivalent file_by_file_id_ contents.");
354      ExpectEquivalent(metadata_database_->file_by_file_id_,
355                       metadata_database_2->file_by_file_id_);
356    }
357
358    {
359      SCOPED_TRACE("Expect equivalent files_by_parent_ contents.");
360      ExpectEquivalent(metadata_database_->files_by_parent_,
361                       metadata_database_2->files_by_parent_);
362    }
363
364    {
365      SCOPED_TRACE("Expect equivalent app_root_by_app_id_ contents.");
366      ExpectEquivalent(metadata_database_->app_root_by_app_id_,
367                       metadata_database_2->app_root_by_app_id_);
368    }
369
370    {
371      SCOPED_TRACE("Expect equivalent"
372                   " active_file_by_parent_and_title_ contents.");
373      ExpectEquivalent(metadata_database_->active_file_by_parent_and_title_,
374                       metadata_database_2->active_file_by_parent_and_title_);
375    }
376
377    {
378      SCOPED_TRACE("Expect equivalent dirty_files_ contents.");
379      ExpectEquivalent(metadata_database_->dirty_files_,
380                       metadata_database_2->dirty_files_);
381    }
382  }
383
384  void VerifyFile(const DriveFileMetadata& file) {
385    DriveFileMetadata file_in_metadata_db;
386    ASSERT_TRUE(metadata_database()->FindFileByFileID(
387        file.file_id(), &file_in_metadata_db));
388
389    SCOPED_TRACE("Expect equivalent " + file.file_id());
390    ExpectEquivalent(&file, &file_in_metadata_db);
391  }
392
393  SyncStatusCode RegisterApp(const std::string& app_id,
394                             const std::string& folder_id) {
395    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
396    metadata_database_->RegisterApp(
397        app_id, folder_id,
398        base::Bind(&SyncStatusResultCallback, &status));
399    message_loop_.RunUntilIdle();
400    return status;
401  }
402
403  SyncStatusCode DisableApp(const std::string& app_id) {
404    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
405    metadata_database_->DisableApp(
406        app_id, base::Bind(&SyncStatusResultCallback, &status));
407    message_loop_.RunUntilIdle();
408    return status;
409  }
410
411  SyncStatusCode EnableApp(const std::string& app_id) {
412    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
413    metadata_database_->EnableApp(
414        app_id, base::Bind(&SyncStatusResultCallback, &status));
415    message_loop_.RunUntilIdle();
416    return status;
417  }
418
419  SyncStatusCode UnregisterApp(const std::string& app_id) {
420    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
421    metadata_database_->UnregisterApp(
422        app_id, base::Bind(&SyncStatusResultCallback, &status));
423    message_loop_.RunUntilIdle();
424    return status;
425  }
426
427  SyncStatusCode UpdateByChangeList(
428      ScopedVector<google_apis::ChangeResource> changes) {
429    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
430    metadata_database_->UpdateByChangeList(
431        changes.Pass(), base::Bind(&SyncStatusResultCallback, &status));
432    message_loop_.RunUntilIdle();
433    return status;
434  }
435
436 private:
437
438  base::ScopedTempDir database_dir_;
439  base::MessageLoop message_loop_;
440
441  scoped_ptr<MetadataDatabase> metadata_database_;
442
443  int64 next_change_id_;
444  int64 next_file_id_number_;
445  int64 next_md5_sequence_number_;
446
447  DISALLOW_COPY_AND_ASSIGN(MetadataDatabaseTest);
448};
449
450TEST_F(MetadataDatabaseTest, InitializationTest_Empty) {
451  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
452  DropDatabase();
453  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
454}
455
456TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) {
457  std::string app_id = "app_id";
458  DriveFileMetadata sync_root(CreateSyncRootMetadata());
459  DriveFileMetadata app_root(CreateAppRootMetadata(sync_root, "app_id"));
460  DriveFileMetadata file(CreateFileMetadata(app_root, "file"));
461  DriveFileMetadata folder(CreateFolderMetadata(app_root, "folder"));
462  DriveFileMetadata file_in_folder(
463      CreateFileMetadata(folder, "file_in_folder"));
464  DriveFileMetadata orphaned(CreateUnknownFileMetadata(sync_root));
465  orphaned.set_parent_folder_id(std::string());
466
467  {
468    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
469    ASSERT_TRUE(db);
470
471    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
472    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
473    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
474    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
475    EXPECT_TRUE(PutFileToDB(db.get(), file_in_folder).ok());
476    EXPECT_TRUE(PutFileToDB(db.get(), orphaned).ok());
477  }
478
479  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
480
481  VerifyFile(sync_root);
482  VerifyFile(app_root);
483  VerifyFile(file);
484  VerifyFile(folder);
485  VerifyFile(file_in_folder);
486  EXPECT_FALSE(metadata_database()->FindFileByFileID(orphaned.file_id(), NULL));
487}
488
489TEST_F(MetadataDatabaseTest, AppManagementTest) {
490  DriveFileMetadata sync_root(CreateSyncRootMetadata());
491  DriveFileMetadata app_root(CreateAppRootMetadata(sync_root, "app_id"));
492  DriveFileMetadata folder(CreateFolderMetadata(sync_root, "folder"));
493  folder.set_active(false);
494
495  {
496    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
497    ASSERT_TRUE(db);
498
499    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
500    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
501    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
502  }
503
504  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
505  VerifyFile(sync_root);
506  VerifyFile(app_root);
507  VerifyFile(folder);
508
509  folder.set_app_id("foo");
510  EXPECT_EQ(SYNC_STATUS_OK, RegisterApp(folder.app_id(), folder.file_id()));
511
512  folder.set_is_app_root(true);
513  folder.set_active(true);
514  folder.set_dirty(true);
515  folder.set_needs_folder_listing(true);
516  VerifyFile(folder);
517  VerifyReloadConsistency();
518
519  EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder.app_id()));
520  folder.set_active(false);
521  VerifyFile(folder);
522  VerifyReloadConsistency();
523
524  EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder.app_id()));
525  folder.set_active(true);
526  VerifyFile(folder);
527  VerifyReloadConsistency();
528
529  EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder.app_id()));
530  folder.set_app_id(std::string());
531  folder.set_is_app_root(false);
532  folder.set_active(false);
533  VerifyFile(folder);
534  VerifyReloadConsistency();
535}
536
537TEST_F(MetadataDatabaseTest, BuildPathTest) {
538  DriveFileMetadata sync_root(CreateSyncRootMetadata());
539  DriveFileMetadata app_root(
540      CreateAppRootMetadata(sync_root, "app_id"));
541  DriveFileMetadata folder(CreateFolderMetadata(app_root, "folder"));
542  DriveFileMetadata file(CreateFolderMetadata(folder, "file"));
543  DriveFileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder"));
544
545  {
546    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
547    ASSERT_TRUE(db);
548
549    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
550    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
551    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
552    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
553  }
554
555  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
556
557  base::FilePath path;
558  EXPECT_FALSE(metadata_database()->BuildPathForFile(sync_root.file_id(),
559                                                     &path));
560  EXPECT_TRUE(metadata_database()->BuildPathForFile(app_root.file_id(), &path));
561  EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(),
562            path);
563  EXPECT_TRUE(metadata_database()->BuildPathForFile(file.file_id(), &path));
564  EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(),
565            path);
566}
567
568TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
569  DriveFileMetadata sync_root(CreateSyncRootMetadata());
570  DriveFileMetadata app_root(CreateAppRootMetadata(sync_root, "app_id"));
571  DriveFileMetadata disabled_app_root(
572      CreateAppRootMetadata(sync_root, "disabled_app"));
573  DriveFileMetadata file(CreateFileMetadata(app_root, "file"));
574  DriveFileMetadata renamed_file(CreateFileMetadata(app_root, "to be renamed"));
575  DriveFileMetadata folder(CreateFolderMetadata(app_root, "folder"));
576  DriveFileMetadata reorganized_file(
577      CreateFileMetadata(app_root, "to be reorganized"));
578  DriveFileMetadata updated_file(CreateFileMetadata(app_root, "to be updated"));
579  DriveFileMetadata noop_file(CreateFileMetadata(app_root, "have noop change"));
580  DriveFileMetadata new_file(CreateFileMetadata(app_root, "to be added later"));
581
582  {
583    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
584    ASSERT_TRUE(db);
585
586    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
587    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
588    EXPECT_TRUE(PutFileToDB(db.get(), disabled_app_root).ok());
589    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
590    EXPECT_TRUE(PutFileToDB(db.get(), renamed_file).ok());
591    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
592    EXPECT_TRUE(PutFileToDB(db.get(), reorganized_file).ok());
593    EXPECT_TRUE(PutFileToDB(db.get(), updated_file).ok());
594    EXPECT_TRUE(PutFileToDB(db.get(), noop_file).ok());
595  }
596
597  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
598
599  ApplyRenameChangeToMetadata("renamed", &renamed_file);
600  ApplyReorganizeChangeToMetadata(folder.file_id(), &reorganized_file);
601  ApplyContentChangeToMetadata(&updated_file);
602  ApplyNoopChangeToMetadata(&noop_file);
603  ApplyNewFileChangeToMetadata(&new_file);
604
605  ScopedVector<google_apis::ChangeResource> changes;
606  PushToChangeList(CreateChangeResourceFromMetadata(renamed_file), &changes);
607  PushToChangeList(CreateChangeResourceFromMetadata(
608      reorganized_file), &changes);
609  PushToChangeList(CreateChangeResourceFromMetadata(updated_file), &changes);
610  PushToChangeList(CreateChangeResourceFromMetadata(noop_file), &changes);
611  PushToChangeList(CreateChangeResourceFromMetadata(new_file), &changes);
612  EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass()));
613
614  VerifyFile(sync_root);
615  VerifyFile(app_root);
616  VerifyFile(disabled_app_root);
617  VerifyFile(file);
618  VerifyFile(renamed_file);
619  VerifyFile(folder);
620  VerifyFile(reorganized_file);
621  VerifyFile(updated_file);
622  VerifyFile(noop_file);
623  VerifyFile(new_file);
624  VerifyReloadConsistency();
625}
626
627}  // namespace drive_backend
628}  // namespace sync_file_system
629