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