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