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