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