107f93fe92331f27526d2e101358aa267f5c849a
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / metadata_database_unittest.cc
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/drive_backend_constants.h"
13 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
15 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
16 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
17 #include "google_apis/drive/drive_api_parser.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/leveldatabase/src/include/leveldb/db.h"
20 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
21
22 #define FPL(a) FILE_PATH_LITERAL(a)
23
24 namespace sync_file_system {
25 namespace drive_backend {
26
27 namespace {
28
29 typedef MetadataDatabase::FileIDList FileIDList;
30
31 const int64 kInitialChangeID = 1234;
32 const int64 kSyncRootTrackerID = 100;
33 const char kSyncRootFolderID[] = "sync_root_folder_id";
34
35 // This struct is used to setup initial state of the database in the test and
36 // also used to match to the modified content of the database as the
37 // expectation.
38 struct TrackedFile {
39   // Holds the latest remote metadata which may be not-yet-synced to |tracker|.
40   FileMetadata metadata;
41   FileTracker tracker;
42
43   // Implies the file should not in the database.
44   bool should_be_absent;
45
46   // Implies the file should have a tracker in the database but should have no
47   // metadata.
48   bool tracker_only;
49
50   TrackedFile() : should_be_absent(false), tracker_only(false) {}
51 };
52
53 void ExpectEquivalent(const ServiceMetadata* left,
54                       const ServiceMetadata* right) {
55   test_util::ExpectEquivalentServiceMetadata(*left, *right);
56 }
57
58 void ExpectEquivalent(const FileMetadata* left, const FileMetadata* right) {
59   if (!left) {
60     ASSERT_FALSE(right);
61     return;
62   }
63   ASSERT_TRUE(right);
64   test_util::ExpectEquivalentMetadata(*left, *right);
65 }
66
67 void ExpectEquivalent(const FileTracker* left, const FileTracker* right) {
68   if (!left) {
69     ASSERT_FALSE(right);
70     return;
71   }
72   ASSERT_TRUE(right);
73   test_util::ExpectEquivalentTrackers(*left, *right);
74 }
75
76 template <typename Container>
77 void ExpectEquivalentMaps(const Container& left, const Container& right);
78 template <typename Key, typename Value, typename Compare>
79 void ExpectEquivalent(const std::map<Key, Value, Compare>& left,
80                       const std::map<Key, Value, Compare>& right) {
81   ExpectEquivalentMaps(left, right);
82 }
83
84 template <typename Container>
85 void ExpectEquivalentSets(const Container& left, const Container& right);
86 template <typename Value, typename Compare>
87 void ExpectEquivalent(const std::set<Value, Compare>& left,
88                       const std::set<Value, Compare>& right) {
89   return ExpectEquivalentSets(left, right);
90 }
91
92 void ExpectEquivalent(const TrackerSet& left,
93                       const TrackerSet& right) {
94   {
95     SCOPED_TRACE("Expect equivalent active_tracker");
96     ExpectEquivalent(left.active_tracker(), right.active_tracker());
97   }
98   ExpectEquivalent(left.tracker_set(), right.tracker_set());
99 }
100
101 template <typename Container>
102 void ExpectEquivalentMaps(const Container& left, const Container& right) {
103   ASSERT_EQ(left.size(), right.size());
104
105   typedef typename Container::const_iterator const_iterator;
106   const_iterator left_itr = left.begin();
107   const_iterator right_itr = right.begin();
108   while (left_itr != left.end()) {
109     EXPECT_EQ(left_itr->first, right_itr->first);
110     ExpectEquivalent(left_itr->second, right_itr->second);
111     ++left_itr;
112     ++right_itr;
113   }
114 }
115
116 template <typename Container>
117 void ExpectEquivalentSets(const Container& left, const Container& right) {
118   ASSERT_EQ(left.size(), right.size());
119
120   typedef typename Container::const_iterator const_iterator;
121   const_iterator left_itr = left.begin();
122   const_iterator right_itr = right.begin();
123   while (left_itr != left.end()) {
124     ExpectEquivalent(*left_itr, *right_itr);
125     ++left_itr;
126     ++right_itr;
127   }
128 }
129
130 base::FilePath CreateNormalizedPath(const base::FilePath::StringType& path) {
131   return base::FilePath(path).NormalizePathSeparators();
132 }
133
134 }  // namespace
135
136 class MetadataDatabaseTest : public testing::Test {
137  public:
138   MetadataDatabaseTest()
139       : current_change_id_(kInitialChangeID),
140         next_tracker_id_(kSyncRootTrackerID + 1),
141         next_file_id_number_(1),
142         next_md5_sequence_number_(1) {}
143
144   virtual ~MetadataDatabaseTest() {}
145
146   virtual void SetUp() OVERRIDE {
147     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
148   }
149
150   virtual void TearDown() OVERRIDE { DropDatabase(); }
151
152  protected:
153   std::string GenerateFileID() {
154     return "file_id_" + base::Int64ToString(next_file_id_number_++);
155   }
156
157   int64 GetTrackerIDByFileID(const std::string& file_id) {
158     TrackerSet trackers;
159     if (metadata_database_->FindTrackersByFileID(file_id, &trackers)) {
160       EXPECT_FALSE(trackers.empty());
161       return (*trackers.begin())->tracker_id();
162     }
163     return 0;
164   }
165
166   SyncStatusCode InitializeMetadataDatabase() {
167     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
168     MetadataDatabase::Create(base::MessageLoopProxy::current(),
169                              database_dir_.path(),
170                              CreateResultReceiver(&status,
171                                                   &metadata_database_));
172     message_loop_.RunUntilIdle();
173     return status;
174   }
175
176   void DropDatabase() {
177     metadata_database_.reset();
178     message_loop_.RunUntilIdle();
179   }
180
181   void SetUpDatabaseByTrackedFiles(const TrackedFile** tracked_files,
182                                    int size) {
183     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
184     ASSERT_TRUE(db);
185
186     for (int i = 0; i < size; ++i) {
187       const TrackedFile* file = tracked_files[i];
188       if (file->should_be_absent)
189         continue;
190       if (!file->tracker_only)
191         EXPECT_TRUE(PutFileToDB(db.get(), file->metadata).ok());
192       EXPECT_TRUE(PutTrackerToDB(db.get(), file->tracker).ok());
193     }
194   }
195
196   void VerifyTrackedFile(const TrackedFile& file) {
197     if (!file.should_be_absent) {
198       if (file.tracker_only) {
199         EXPECT_FALSE(metadata_database()->FindFileByFileID(
200             file.metadata.file_id(), NULL));
201       } else {
202         VerifyFile(file.metadata);
203       }
204       VerifyTracker(file.tracker);
205       return;
206     }
207
208     EXPECT_FALSE(metadata_database()->FindFileByFileID(
209         file.metadata.file_id(), NULL));
210     EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
211         file.tracker.tracker_id(), NULL));
212   }
213
214   void VerifyTrackedFiles(const TrackedFile** tracked_files, int size) {
215     for (int i = 0; i < size; ++i)
216       VerifyTrackedFile(*tracked_files[i]);
217   }
218
219   MetadataDatabase* metadata_database() { return metadata_database_.get(); }
220
221   scoped_ptr<leveldb::DB> InitializeLevelDB() {
222     leveldb::DB* db = NULL;
223     leveldb::Options options;
224     options.create_if_missing = true;
225     options.max_open_files = 0;  // Use minimum.
226     leveldb::Status status =
227         leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
228     EXPECT_TRUE(status.ok());
229
230     db->Put(leveldb::WriteOptions(),
231             kDatabaseVersionKey,
232             base::Int64ToString(3));
233     SetUpServiceMetadata(db);
234
235     return make_scoped_ptr(db);
236   }
237
238   void SetUpServiceMetadata(leveldb::DB* db) {
239     ServiceMetadata service_metadata;
240     service_metadata.set_largest_change_id(kInitialChangeID);
241     service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
242     service_metadata.set_next_tracker_id(next_tracker_id_);
243     leveldb::WriteBatch batch;
244     PutServiceMetadataToBatch(service_metadata, &batch);
245     EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
246   }
247
248   FileMetadata CreateSyncRootMetadata() {
249     FileMetadata sync_root;
250     sync_root.set_file_id(kSyncRootFolderID);
251     FileDetails* details = sync_root.mutable_details();
252     details->set_title(kSyncRootFolderTitle);
253     details->set_file_kind(FILE_KIND_FOLDER);
254     return sync_root;
255   }
256
257   FileMetadata CreateFileMetadata(const FileMetadata& parent,
258                                   const std::string& title) {
259     FileMetadata file;
260     file.set_file_id(GenerateFileID());
261     FileDetails* details = file.mutable_details();
262     details->add_parent_folder_ids(parent.file_id());
263     details->set_title(title);
264     details->set_file_kind(FILE_KIND_FILE);
265     details->set_md5(
266         "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
267     return file;
268   }
269
270   FileMetadata CreateFolderMetadata(const FileMetadata& parent,
271                                     const std::string& title) {
272     FileMetadata folder;
273     folder.set_file_id(GenerateFileID());
274     FileDetails* details = folder.mutable_details();
275     details->add_parent_folder_ids(parent.file_id());
276     details->set_title(title);
277     details->set_file_kind(FILE_KIND_FOLDER);
278     return folder;
279   }
280
281   FileTracker CreateSyncRootTracker(const FileMetadata& sync_root) {
282     FileTracker sync_root_tracker;
283     sync_root_tracker.set_tracker_id(kSyncRootTrackerID);
284     sync_root_tracker.set_parent_tracker_id(0);
285     sync_root_tracker.set_file_id(sync_root.file_id());
286     sync_root_tracker.set_dirty(false);
287     sync_root_tracker.set_active(true);
288     sync_root_tracker.set_needs_folder_listing(false);
289     *sync_root_tracker.mutable_synced_details() = sync_root.details();
290     return sync_root_tracker;
291   }
292
293   FileTracker CreateTracker(const FileTracker& parent_tracker,
294                             const FileMetadata& file) {
295     FileTracker tracker;
296     tracker.set_tracker_id(next_tracker_id_++);
297     tracker.set_parent_tracker_id(parent_tracker.tracker_id());
298     tracker.set_file_id(file.file_id());
299     tracker.set_app_id(parent_tracker.app_id());
300     tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
301     tracker.set_dirty(false);
302     tracker.set_active(true);
303     tracker.set_needs_folder_listing(false);
304     *tracker.mutable_synced_details() = file.details();
305     return tracker;
306   }
307
308   TrackedFile CreateTrackedSyncRoot() {
309     TrackedFile sync_root;
310     sync_root.metadata = CreateSyncRootMetadata();
311     sync_root.tracker = CreateSyncRootTracker(sync_root.metadata);
312     return sync_root;
313   }
314
315   TrackedFile CreateTrackedAppRoot(const TrackedFile& sync_root,
316                                    const std::string& app_id) {
317     TrackedFile app_root(CreateTrackedFolder(sync_root, app_id));
318     app_root.tracker.set_app_id(app_id);
319     app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
320     return app_root;
321   }
322
323   TrackedFile CreateTrackedFile(const TrackedFile& parent,
324                                 const std::string& title) {
325     TrackedFile file;
326     file.metadata = CreateFileMetadata(parent.metadata, title);
327     file.tracker = CreateTracker(parent.tracker, file.metadata);
328     return file;
329   }
330
331   TrackedFile CreateTrackedFolder(const TrackedFile& parent,
332                                   const std::string& title) {
333     TrackedFile folder;
334     folder.metadata = CreateFolderMetadata(parent.metadata, title);
335     folder.tracker = CreateTracker(parent.tracker, folder.metadata);
336     return folder;
337   }
338
339   scoped_ptr<google_apis::FileResource> CreateFileResourceFromMetadata(
340       const FileMetadata& file) {
341     scoped_ptr<google_apis::FileResource> file_resource(
342         new google_apis::FileResource);
343     ScopedVector<google_apis::ParentReference> parents;
344     for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
345       scoped_ptr<google_apis::ParentReference> parent(
346           new google_apis::ParentReference);
347       parent->set_file_id(file.details().parent_folder_ids(i));
348       parents.push_back(parent.release());
349     }
350
351     file_resource->set_file_id(file.file_id());
352     file_resource->set_parents(parents.Pass());
353     file_resource->set_title(file.details().title());
354     if (file.details().file_kind() == FILE_KIND_FOLDER)
355       file_resource->set_mime_type("application/vnd.google-apps.folder");
356     else if (file.details().file_kind() == FILE_KIND_FILE)
357       file_resource->set_mime_type("text/plain");
358     else
359       file_resource->set_mime_type("application/vnd.google-apps.document");
360     file_resource->set_md5_checksum(file.details().md5());
361     file_resource->set_etag(file.details().etag());
362     file_resource->set_created_date(base::Time::FromInternalValue(
363         file.details().creation_time()));
364     file_resource->set_modified_date(base::Time::FromInternalValue(
365         file.details().modification_time()));
366
367     return file_resource.Pass();
368   }
369
370   scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
371       const FileMetadata& file) {
372     scoped_ptr<google_apis::ChangeResource> change(
373         new google_apis::ChangeResource);
374     change->set_change_id(file.details().change_id());
375     change->set_file_id(file.file_id());
376     change->set_deleted(file.details().missing());
377     if (change->is_deleted())
378       return change.Pass();
379
380     change->set_file(CreateFileResourceFromMetadata(file));
381     return change.Pass();
382   }
383
384   void ApplyRenameChangeToMetadata(const std::string& new_title,
385                                    FileMetadata* file) {
386     FileDetails* details = file->mutable_details();
387     details->set_title(new_title);
388     details->set_change_id(++current_change_id_);
389   }
390
391   void ApplyReorganizeChangeToMetadata(const std::string& new_parent,
392                                        FileMetadata* file) {
393     FileDetails* details = file->mutable_details();
394     details->clear_parent_folder_ids();
395     details->add_parent_folder_ids(new_parent);
396     details->set_change_id(++current_change_id_);
397   }
398
399   void ApplyContentChangeToMetadata(FileMetadata* file) {
400     FileDetails* details = file->mutable_details();
401     details->set_md5(
402         "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
403     details->set_change_id(++current_change_id_);
404   }
405
406   void ApplyNoopChangeToMetadata(FileMetadata* file) {
407     file->mutable_details()->set_change_id(++current_change_id_);
408   }
409
410   void PushToChangeList(scoped_ptr<google_apis::ChangeResource> change,
411                         ScopedVector<google_apis::ChangeResource>* changes) {
412     changes->push_back(change.release());
413   }
414
415   leveldb::Status PutFileToDB(leveldb::DB* db, const FileMetadata& file) {
416     leveldb::WriteBatch batch;
417     PutFileToBatch(file, &batch);
418     return db->Write(leveldb::WriteOptions(), &batch);
419   }
420
421   leveldb::Status PutTrackerToDB(leveldb::DB* db,
422                                  const FileTracker& tracker) {
423     leveldb::WriteBatch batch;
424     PutTrackerToBatch(tracker, &batch);
425     return db->Write(leveldb::WriteOptions(), &batch);
426   }
427
428   void VerifyReloadConsistency() {
429     scoped_ptr<MetadataDatabase> metadata_database_2;
430     ASSERT_EQ(SYNC_STATUS_OK,
431               MetadataDatabase::CreateForTesting(
432                   metadata_database_->db_.Pass(),
433                   &metadata_database_2));
434     metadata_database_->db_ = metadata_database_2->db_.Pass();
435
436     {
437       SCOPED_TRACE("Expect equivalent service_metadata");
438       ExpectEquivalent(metadata_database_->service_metadata_.get(),
439                        metadata_database_2->service_metadata_.get());
440     }
441
442     {
443       SCOPED_TRACE("Expect equivalent file_by_id_ contents.");
444       ExpectEquivalent(metadata_database_->file_by_id_,
445                        metadata_database_2->file_by_id_);
446     }
447
448     {
449       SCOPED_TRACE("Expect equivalent tracker_by_id_ contents.");
450       ExpectEquivalent(metadata_database_->tracker_by_id_,
451                        metadata_database_2->tracker_by_id_);
452     }
453
454     {
455       SCOPED_TRACE("Expect equivalent trackers_by_file_id_ contents.");
456       ExpectEquivalent(metadata_database_->trackers_by_file_id_,
457                        metadata_database_2->trackers_by_file_id_);
458     }
459
460     {
461       SCOPED_TRACE("Expect equivalent app_root_by_app_id_ contents.");
462       ExpectEquivalent(metadata_database_->app_root_by_app_id_,
463                        metadata_database_2->app_root_by_app_id_);
464     }
465
466     {
467       SCOPED_TRACE("Expect equivalent trackers_by_parent_and_title_ contents.");
468       ExpectEquivalent(metadata_database_->trackers_by_parent_and_title_,
469                        metadata_database_2->trackers_by_parent_and_title_);
470     }
471
472     {
473       SCOPED_TRACE("Expect equivalent dirty_trackers_ contents.");
474       ExpectEquivalent(metadata_database_->dirty_trackers_,
475                        metadata_database_2->dirty_trackers_);
476     }
477   }
478
479   void VerifyFile(const FileMetadata& file) {
480     FileMetadata file_in_metadata_database;
481     ASSERT_TRUE(metadata_database()->FindFileByFileID(
482         file.file_id(), &file_in_metadata_database));
483
484     SCOPED_TRACE("Expect equivalent " + file.file_id());
485     ExpectEquivalent(&file, &file_in_metadata_database);
486   }
487
488   void VerifyTracker(const FileTracker& tracker) {
489     FileTracker tracker_in_metadata_database;
490     ASSERT_TRUE(metadata_database()->FindTrackerByTrackerID(
491         tracker.tracker_id(), &tracker_in_metadata_database));
492
493     SCOPED_TRACE("Expect equivalent tracker[" +
494                  base::Int64ToString(tracker.tracker_id()) + "]");
495     ExpectEquivalent(&tracker, &tracker_in_metadata_database);
496   }
497
498   SyncStatusCode RegisterApp(const std::string& app_id,
499                              const std::string& folder_id) {
500     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
501     metadata_database_->RegisterApp(
502         app_id, folder_id,
503         CreateResultReceiver(&status));
504     message_loop_.RunUntilIdle();
505     return status;
506   }
507
508   SyncStatusCode DisableApp(const std::string& app_id) {
509     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
510     metadata_database_->DisableApp(
511         app_id, CreateResultReceiver(&status));
512     message_loop_.RunUntilIdle();
513     return status;
514   }
515
516   SyncStatusCode EnableApp(const std::string& app_id) {
517     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
518     metadata_database_->EnableApp(
519         app_id, CreateResultReceiver(&status));
520     message_loop_.RunUntilIdle();
521     return status;
522   }
523
524   SyncStatusCode UnregisterApp(const std::string& app_id) {
525     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
526     metadata_database_->UnregisterApp(
527         app_id, CreateResultReceiver(&status));
528     message_loop_.RunUntilIdle();
529     return status;
530   }
531
532   SyncStatusCode UpdateByChangeList(
533       ScopedVector<google_apis::ChangeResource> changes) {
534     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
535     metadata_database_->UpdateByChangeList(
536         current_change_id_,
537         changes.Pass(), CreateResultReceiver(&status));
538     message_loop_.RunUntilIdle();
539     return status;
540   }
541
542   SyncStatusCode PopulateFolder(const std::string& folder_id,
543                                 const FileIDList& listed_children) {
544     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
545     metadata_database_->PopulateFolderByChildList(
546         folder_id, listed_children,
547         CreateResultReceiver(&status));
548     message_loop_.RunUntilIdle();
549     return status;
550   }
551
552   SyncStatusCode UpdateTracker(const FileTracker& tracker) {
553     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
554     metadata_database_->UpdateTracker(
555         tracker.tracker_id(), tracker.synced_details(),
556         CreateResultReceiver(&status));
557     message_loop_.RunUntilIdle();
558     return status;
559   }
560
561   SyncStatusCode PopulateInitialData(
562       int64 largest_change_id,
563       const google_apis::FileResource& sync_root_folder,
564       const ScopedVector<google_apis::FileResource>& app_root_folders) {
565     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
566     metadata_database_->PopulateInitialData(
567         largest_change_id,
568         sync_root_folder,
569         app_root_folders,
570         CreateResultReceiver(&status));
571     message_loop_.RunUntilIdle();
572     return status;
573   }
574
575   void ResetTrackerID(FileTracker* tracker) {
576     tracker->set_tracker_id(GetTrackerIDByFileID(tracker->file_id()));
577   }
578
579  private:
580   base::ScopedTempDir database_dir_;
581   base::MessageLoop message_loop_;
582
583   scoped_ptr<MetadataDatabase> metadata_database_;
584
585   int64 current_change_id_;
586   int64 next_tracker_id_;
587   int64 next_file_id_number_;
588   int64 next_md5_sequence_number_;
589
590   DISALLOW_COPY_AND_ASSIGN(MetadataDatabaseTest);
591 };
592
593 TEST_F(MetadataDatabaseTest, InitializationTest_Empty) {
594   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
595   DropDatabase();
596   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
597 }
598
599 TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) {
600   TrackedFile sync_root(CreateTrackedSyncRoot());
601   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id"));
602   app_root.tracker.set_app_id(app_root.metadata.details().title());
603   app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
604
605   TrackedFile file(CreateTrackedFile(app_root, "file"));
606   TrackedFile folder(CreateTrackedFolder(app_root, "folder"));
607   TrackedFile file_in_folder(CreateTrackedFile(folder, "file_in_folder"));
608   TrackedFile orphaned_file(CreateTrackedFile(sync_root, "orphaned_file"));
609   orphaned_file.metadata.mutable_details()->clear_parent_folder_ids();
610   orphaned_file.tracker.set_parent_tracker_id(0);
611
612   const TrackedFile* tracked_files[] = {
613     &sync_root, &app_root, &file, &folder, &file_in_folder, &orphaned_file
614   };
615
616   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
617   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
618
619   orphaned_file.should_be_absent = true;
620   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
621 }
622
623 TEST_F(MetadataDatabaseTest, AppManagementTest) {
624   TrackedFile sync_root(CreateTrackedSyncRoot());
625   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id"));
626   app_root.tracker.set_app_id(app_root.metadata.details().title());
627   app_root.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
628
629   TrackedFile file(CreateTrackedFile(app_root, "file"));
630   TrackedFile folder(CreateTrackedFolder(sync_root, "folder"));
631   folder.tracker.set_active(false);
632
633   const TrackedFile* tracked_files[] = {
634     &sync_root, &app_root, &file, &folder,
635   };
636   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
637   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
638   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
639
640   folder.tracker.set_app_id("foo");
641   EXPECT_EQ(SYNC_STATUS_OK, RegisterApp(
642       folder.tracker.app_id(), folder.metadata.file_id()));
643   folder.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
644   folder.tracker.set_active(true);
645   folder.tracker.set_dirty(true);
646   folder.tracker.set_needs_folder_listing(true);
647   VerifyTrackedFile(folder);
648   VerifyReloadConsistency();
649
650   EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder.tracker.app_id()));
651   folder.tracker.set_tracker_kind(TRACKER_KIND_DISABLED_APP_ROOT);
652   VerifyTrackedFile(folder);
653   VerifyReloadConsistency();
654
655   EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder.tracker.app_id()));
656   folder.tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
657   VerifyTrackedFile(folder);
658   VerifyReloadConsistency();
659
660   EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder.tracker.app_id()));
661   folder.tracker.set_app_id(std::string());
662   folder.tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
663   folder.tracker.set_active(false);
664   VerifyTrackedFile(folder);
665   VerifyReloadConsistency();
666
667   EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(app_root.tracker.app_id()));
668   app_root.tracker.set_app_id(std::string());
669   app_root.tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
670   app_root.tracker.set_active(false);
671   app_root.tracker.set_dirty(true);
672   file.should_be_absent = true;
673   VerifyTrackedFile(app_root);
674   VerifyTrackedFile(file);
675   VerifyReloadConsistency();
676 }
677
678 TEST_F(MetadataDatabaseTest, BuildPathTest) {
679   FileMetadata sync_root(CreateSyncRootMetadata());
680   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
681
682   FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
683   FileTracker app_root_tracker(
684       CreateTracker(sync_root_tracker, app_root));
685   app_root_tracker.set_app_id(app_root.details().title());
686   app_root_tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
687
688   FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
689   FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
690
691   FileMetadata file(CreateFileMetadata(folder, "file"));
692   FileTracker file_tracker(CreateTracker(folder_tracker, file));
693
694   FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder"));
695   FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
696                                                     inactive_folder));
697   inactive_folder_tracker.set_active(false);
698
699   {
700     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
701     ASSERT_TRUE(db);
702
703     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
704     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
705     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
706     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
707     EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
708     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
709     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
710     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
711   }
712
713   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
714
715   base::FilePath path;
716   EXPECT_FALSE(metadata_database()->BuildPathForTracker(
717       sync_root_tracker.tracker_id(), &path));
718   EXPECT_TRUE(metadata_database()->BuildPathForTracker(
719       app_root_tracker.tracker_id(), &path));
720   EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(), path);
721   EXPECT_TRUE(metadata_database()->BuildPathForTracker(
722       file_tracker.tracker_id(), &path));
723   EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(),
724             path);
725 }
726
727 TEST_F(MetadataDatabaseTest, FindNearestActiveAncestorTest) {
728   const std::string kAppID = "app_id";
729
730   FileMetadata sync_root(CreateSyncRootMetadata());
731   FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
732
733   FileMetadata app_root(CreateFolderMetadata(sync_root, kAppID));
734   FileTracker app_root_tracker(
735       CreateTracker(sync_root_tracker, app_root));
736   app_root_tracker.set_app_id(app_root.details().title());
737   app_root_tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
738
739   // Create directory structure like this: "/folder1/folder2/file"
740   FileMetadata folder1(CreateFolderMetadata(app_root, "folder1"));
741   FileTracker folder_tracker1(CreateTracker(app_root_tracker, folder1));
742   FileMetadata folder2(CreateFolderMetadata(folder1, "folder2"));
743   FileTracker folder_tracker2(CreateTracker(folder_tracker1, folder2));
744   FileMetadata file(CreateFileMetadata(folder2, "file"));
745   FileTracker file_tracker(CreateTracker(folder_tracker2, file));
746
747   FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder1"));
748   FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
749                                                     inactive_folder));
750   inactive_folder_tracker.set_active(false);
751
752   {
753     scoped_ptr<leveldb::DB> db = InitializeLevelDB();
754     ASSERT_TRUE(db);
755
756     EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
757     EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
758     EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
759     EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
760     EXPECT_TRUE(PutFileToDB(db.get(), folder1).ok());
761     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker1).ok());
762     EXPECT_TRUE(PutFileToDB(db.get(), folder2).ok());
763     EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker2).ok());
764     EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
765     EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
766     EXPECT_TRUE(PutFileToDB(db.get(), inactive_folder).ok());
767     EXPECT_TRUE(PutTrackerToDB(db.get(), inactive_folder_tracker).ok());
768   }
769
770   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
771
772   {
773     base::FilePath path;
774     FileTracker tracker;
775     EXPECT_FALSE(metadata_database()->FindNearestActiveAncestor(
776         "non_registered_app_id",
777         CreateNormalizedPath(FPL("folder1/folder2/file")),
778         &tracker, &path));
779   }
780
781   {
782     base::FilePath path;
783     FileTracker tracker;
784     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
785         kAppID, CreateNormalizedPath(FPL("")), &tracker, &path));
786     EXPECT_EQ(app_root_tracker.tracker_id(), tracker.tracker_id());
787     EXPECT_EQ(CreateNormalizedPath(FPL("")), path);
788   }
789
790   {
791     base::FilePath path;
792     FileTracker tracker;
793     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
794         kAppID, CreateNormalizedPath(FPL("folder1/folder2")),
795         &tracker, &path));
796     EXPECT_EQ(folder_tracker2.tracker_id(), tracker.tracker_id());
797     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2")), path);
798   }
799
800   {
801     base::FilePath path;
802     FileTracker tracker;
803     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
804         kAppID, CreateNormalizedPath(FPL("folder1/folder2/file")),
805         &tracker, &path));
806     EXPECT_EQ(file_tracker.tracker_id(), tracker.tracker_id());
807     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2/file")), path);
808   }
809
810   {
811     base::FilePath path;
812     FileTracker tracker;
813     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
814         kAppID,
815         CreateNormalizedPath(FPL("folder1/folder2/folder3/folder4/file")),
816         &tracker, &path));
817     EXPECT_EQ(folder_tracker2.tracker_id(), tracker.tracker_id());
818     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2")), path);
819   }
820
821   {
822     base::FilePath path;
823     FileTracker tracker;
824     EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
825         kAppID, CreateNormalizedPath(FPL("folder1/folder2/file/folder4/file")),
826         &tracker, &path));
827     EXPECT_EQ(folder_tracker2.tracker_id(), tracker.tracker_id());
828     EXPECT_EQ(CreateNormalizedPath(FPL("folder1/folder2")), path);
829   }
830 }
831
832 TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
833   TrackedFile sync_root(CreateTrackedSyncRoot());
834   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_id"));
835   TrackedFile disabled_app_root(CreateTrackedFolder(sync_root, "disabled_app"));
836   TrackedFile file(CreateTrackedFile(app_root, "file"));
837   TrackedFile renamed_file(CreateTrackedFile(app_root, "to be renamed"));
838   TrackedFile folder(CreateTrackedFolder(app_root, "folder"));
839   TrackedFile reorganized_file(
840       CreateTrackedFile(app_root, "to be reorganized"));
841   TrackedFile updated_file(
842       CreateTrackedFile(app_root, "to be updated"));
843   TrackedFile noop_file(CreateTrackedFile(app_root, "has noop change"));
844   TrackedFile new_file(CreateTrackedFile(app_root, "to be added later"));
845   new_file.should_be_absent = true;
846
847   const TrackedFile* tracked_files[] = {
848     &sync_root, &app_root, &disabled_app_root,
849     &file, &renamed_file, &folder, &reorganized_file, &updated_file, &noop_file,
850     &new_file,
851   };
852
853   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
854   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
855
856   ApplyRenameChangeToMetadata("renamed", &renamed_file.metadata);
857   ApplyReorganizeChangeToMetadata(folder.metadata.file_id(),
858                                   &reorganized_file.metadata);
859   ApplyContentChangeToMetadata(&updated_file.metadata);
860
861   // Update change ID.
862   ApplyNoopChangeToMetadata(&noop_file.metadata);
863
864   ScopedVector<google_apis::ChangeResource> changes;
865   PushToChangeList(
866       CreateChangeResourceFromMetadata(renamed_file.metadata), &changes);
867   PushToChangeList(
868       CreateChangeResourceFromMetadata(reorganized_file.metadata), &changes);
869   PushToChangeList(
870       CreateChangeResourceFromMetadata(updated_file.metadata), &changes);
871   PushToChangeList(
872       CreateChangeResourceFromMetadata(noop_file.metadata), &changes);
873   PushToChangeList(
874       CreateChangeResourceFromMetadata(new_file.metadata), &changes);
875   EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass()));
876
877   renamed_file.tracker.set_dirty(true);
878   reorganized_file.tracker.set_dirty(true);
879   updated_file.tracker.set_dirty(true);
880   noop_file.tracker.set_dirty(true);
881   new_file.tracker.mutable_synced_details()->set_missing(true);
882   new_file.tracker.mutable_synced_details()->clear_md5();
883   new_file.tracker.set_active(false);
884   new_file.tracker.set_dirty(true);
885   ResetTrackerID(&new_file.tracker);
886   EXPECT_NE(0, new_file.tracker.tracker_id());
887
888   new_file.should_be_absent = false;
889
890   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
891   VerifyReloadConsistency();
892 }
893
894 TEST_F(MetadataDatabaseTest, PopulateFolderTest_RegularFolder) {
895   TrackedFile sync_root(CreateTrackedSyncRoot());
896   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id"));
897   app_root.tracker.set_app_id(app_root.metadata.details().title());
898
899   TrackedFile folder_to_populate(
900       CreateTrackedFolder(app_root, "folder_to_populate"));
901   folder_to_populate.tracker.set_needs_folder_listing(true);
902   folder_to_populate.tracker.set_dirty(true);
903
904   TrackedFile known_file(CreateTrackedFile(folder_to_populate, "known_file"));
905   TrackedFile new_file(CreateTrackedFile(folder_to_populate, "new_file"));
906   new_file.should_be_absent = true;
907
908   const TrackedFile* tracked_files[] = {
909     &sync_root, &app_root, &folder_to_populate, &known_file, &new_file
910   };
911
912   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
913   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
914   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
915
916   FileIDList listed_children;
917   listed_children.push_back(known_file.metadata.file_id());
918   listed_children.push_back(new_file.metadata.file_id());
919
920   EXPECT_EQ(SYNC_STATUS_OK,
921             PopulateFolder(folder_to_populate.metadata.file_id(),
922                            listed_children));
923
924   folder_to_populate.tracker.set_dirty(false);
925   folder_to_populate.tracker.set_needs_folder_listing(false);
926   ResetTrackerID(&new_file.tracker);
927   new_file.tracker.set_dirty(true);
928   new_file.tracker.set_active(false);
929   new_file.tracker.clear_synced_details();
930   new_file.should_be_absent = false;
931   new_file.tracker_only = true;
932   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
933   VerifyReloadConsistency();
934 }
935
936 TEST_F(MetadataDatabaseTest, PopulateFolderTest_InactiveFolder) {
937   TrackedFile sync_root(CreateTrackedSyncRoot());
938   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id"));
939
940   TrackedFile inactive_folder(CreateTrackedFolder(app_root, "inactive_folder"));
941   inactive_folder.tracker.set_active(false);
942   inactive_folder.tracker.set_dirty(true);
943
944   TrackedFile new_file(
945       CreateTrackedFile(inactive_folder, "file_in_inactive_folder"));
946   new_file.should_be_absent = true;
947
948   const TrackedFile* tracked_files[] = {
949     &sync_root, &app_root, &inactive_folder, &new_file,
950   };
951
952   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
953   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
954   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
955
956   FileIDList listed_children;
957   listed_children.push_back(new_file.metadata.file_id());
958
959   EXPECT_EQ(SYNC_STATUS_OK,
960             PopulateFolder(inactive_folder.metadata.file_id(),
961                            listed_children));
962   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
963   VerifyReloadConsistency();
964 }
965
966 TEST_F(MetadataDatabaseTest, PopulateFolderTest_DisabledAppRoot) {
967   TrackedFile sync_root(CreateTrackedSyncRoot());
968   TrackedFile disabled_app_root(
969       CreateTrackedAppRoot(sync_root, "disabled_app"));
970   disabled_app_root.tracker.set_dirty(true);
971   disabled_app_root.tracker.set_needs_folder_listing(true);
972
973   TrackedFile known_file(CreateTrackedFile(disabled_app_root, "known_file"));
974   TrackedFile file(CreateTrackedFile(disabled_app_root, "file"));
975   file.should_be_absent = true;
976
977   const TrackedFile* tracked_files[] = {
978     &sync_root, &disabled_app_root, &disabled_app_root, &known_file, &file,
979   };
980
981   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
982   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
983   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
984
985   FileIDList disabled_app_children;
986   disabled_app_children.push_back(file.metadata.file_id());
987   EXPECT_EQ(SYNC_STATUS_OK, PopulateFolder(
988       disabled_app_root.metadata.file_id(), disabled_app_children));
989   ResetTrackerID(&file.tracker);
990   file.tracker.clear_synced_details();
991   file.tracker.set_dirty(true);
992   file.tracker.set_active(false);
993   file.should_be_absent = false;
994   file.tracker_only = true;
995
996   disabled_app_root.tracker.set_dirty(false);
997   disabled_app_root.tracker.set_needs_folder_listing(false);
998   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
999   VerifyReloadConsistency();
1000 }
1001
1002 // TODO(tzik): Fix expectation and re-enable this test.
1003 TEST_F(MetadataDatabaseTest, DISABLED_UpdateTrackerTest) {
1004   TrackedFile sync_root(CreateTrackedSyncRoot());
1005   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_root"));
1006   TrackedFile file(CreateTrackedFile(app_root, "file"));
1007   file.tracker.set_dirty(true);
1008   file.metadata.mutable_details()->set_title("renamed file");
1009
1010   TrackedFile inactive_file(CreateTrackedFile(app_root, "inactive_file"));
1011   inactive_file.tracker.set_active(false);
1012   inactive_file.tracker.set_dirty(true);
1013   inactive_file.metadata.mutable_details()->set_title("renamed inactive file");
1014   inactive_file.metadata.mutable_details()->set_md5("modified_md5");
1015
1016   TrackedFile new_conflict(CreateTrackedFile(app_root, "new conflict file"));
1017   new_conflict.tracker.set_dirty(true);
1018   new_conflict.metadata.mutable_details()->set_title("renamed file");
1019
1020   const TrackedFile* tracked_files[] = {
1021     &sync_root, &app_root, &file, &inactive_file, &new_conflict
1022   };
1023
1024   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
1025   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
1026   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
1027   VerifyReloadConsistency();
1028
1029   *file.tracker.mutable_synced_details() = file.metadata.details();
1030   file.tracker.set_dirty(false);
1031   EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(file.tracker));
1032   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
1033   VerifyReloadConsistency();
1034
1035   *inactive_file.tracker.mutable_synced_details() =
1036        inactive_file.metadata.details();
1037   inactive_file.tracker.set_dirty(false);
1038   inactive_file.tracker.set_active(true);
1039   EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(inactive_file.tracker));
1040   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
1041   VerifyReloadConsistency();
1042
1043   *new_conflict.tracker.mutable_synced_details() =
1044        new_conflict.metadata.details();
1045   new_conflict.tracker.set_dirty(false);
1046   new_conflict.tracker.set_active(true);
1047   file.tracker.set_dirty(true);
1048   file.tracker.set_active(false);
1049   EXPECT_EQ(SYNC_STATUS_OK, UpdateTracker(new_conflict.tracker));
1050   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
1051   VerifyReloadConsistency();
1052 }
1053
1054 TEST_F(MetadataDatabaseTest, PopulateInitialDataTest) {
1055   TrackedFile sync_root(CreateTrackedSyncRoot());
1056   TrackedFile app_root(CreateTrackedFolder(sync_root, "app_root"));
1057   app_root.tracker.set_active(false);
1058
1059   const TrackedFile* tracked_files[] = {
1060     &sync_root, &app_root
1061   };
1062
1063   int64 largest_change_id = 42;
1064   scoped_ptr<google_apis::FileResource> sync_root_folder(
1065       CreateFileResourceFromMetadata(sync_root.metadata));
1066   scoped_ptr<google_apis::FileResource> app_root_folder(
1067       CreateFileResourceFromMetadata(app_root.metadata));
1068
1069   ScopedVector<google_apis::FileResource> app_root_folders;
1070   app_root_folders.push_back(app_root_folder.release());
1071
1072   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
1073   EXPECT_EQ(SYNC_STATUS_OK, PopulateInitialData(
1074       largest_change_id,
1075       *sync_root_folder,
1076       app_root_folders));
1077
1078   ResetTrackerID(&sync_root.tracker);
1079   ResetTrackerID(&app_root.tracker);
1080   app_root.tracker.set_parent_tracker_id(sync_root.tracker.tracker_id());
1081
1082   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
1083   VerifyReloadConsistency();
1084 }
1085
1086 TEST_F(MetadataDatabaseTest, DumpFiles) {
1087   TrackedFile sync_root(CreateTrackedSyncRoot());
1088   TrackedFile app_root(CreateTrackedAppRoot(sync_root, "app_id"));
1089   app_root.tracker.set_app_id(app_root.metadata.details().title());
1090
1091   TrackedFile folder_0(CreateTrackedFolder(app_root, "folder_0"));
1092   TrackedFile file_0(CreateTrackedFile(folder_0, "file_0"));
1093
1094   const TrackedFile* tracked_files[] = {
1095     &sync_root, &app_root, &folder_0, &file_0
1096   };
1097
1098   SetUpDatabaseByTrackedFiles(tracked_files, arraysize(tracked_files));
1099   EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
1100   VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
1101
1102   scoped_ptr<base::ListValue> files =
1103       metadata_database()->DumpFiles(app_root.tracker.app_id());
1104   ASSERT_EQ(2u, files->GetSize());
1105
1106   base::DictionaryValue* file = NULL;
1107   std::string str;
1108
1109   ASSERT_TRUE(files->GetDictionary(0, &file));
1110   EXPECT_TRUE(file->GetString("title", &str) && str == "folder_0");
1111   EXPECT_TRUE(file->GetString("type", &str) && str == "folder");
1112   EXPECT_TRUE(file->HasKey("details"));
1113
1114   ASSERT_TRUE(files->GetDictionary(1, &file));
1115   EXPECT_TRUE(file->GetString("title", &str) && str == "file_0");
1116   EXPECT_TRUE(file->GetString("type", &str) && str == "file");
1117   EXPECT_TRUE(file->HasKey("details"));
1118 }
1119
1120 }  // namespace drive_backend
1121 }  // namespace sync_file_system