metadata_database_unittest.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
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/google_apis/drive_api_parser.h"
13#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
14#include "testing/gtest/include/gtest/gtest.h"
15#include "third_party/leveldatabase/src/include/leveldb/db.h"
16#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
17
18#define FPL(a) FILE_PATH_LITERAL(a)
19
20namespace sync_file_system {
21namespace drive_backend {
22
23namespace {
24
25const int64 kInitialChangeID = 1234;
26const int64 kSyncRootTrackerID = 100;
27const char kSyncRootFolderID[] = "sync_root_folder_id";
28
29void ExpectEquivalent(const ServiceMetadata* left,
30                      const ServiceMetadata* right) {
31  if (!left) {
32    ASSERT_FALSE(right);
33    return;
34  }
35  ASSERT_TRUE(right);
36
37  EXPECT_EQ(left->largest_change_id(), right->largest_change_id());
38  EXPECT_EQ(left->sync_root_tracker_id(), right->sync_root_tracker_id());
39  EXPECT_EQ(left->next_tracker_id(), right->next_tracker_id());
40}
41
42void ExpectEquivalent(const FileDetails* left, const FileDetails* right) {
43  if (!left) {
44    ASSERT_FALSE(right);
45    return;
46  }
47  ASSERT_TRUE(right);
48
49  std::set<std::string> parents;
50  for (int i = 0; i < left->parent_folder_ids_size(); ++i)
51    EXPECT_TRUE(parents.insert(left->parent_folder_ids(i)).second);
52
53  for (int i = 0; i < right->parent_folder_ids_size(); ++i)
54    EXPECT_EQ(1u, parents.erase(left->parent_folder_ids(i)));
55  EXPECT_TRUE(parents.empty());
56
57  EXPECT_EQ(left->title(), right->title());
58  EXPECT_EQ(left->file_kind(), right->file_kind());
59  EXPECT_EQ(left->md5(), right->md5());
60  EXPECT_EQ(left->etag(), right->etag());
61  EXPECT_EQ(left->creation_time(), right->creation_time());
62  EXPECT_EQ(left->modification_time(), right->modification_time());
63  EXPECT_EQ(left->deleted(), right->deleted());
64  EXPECT_EQ(left->change_id(), right->change_id());
65}
66
67void ExpectEquivalent(const FileMetadata* left, const FileMetadata* right) {
68  if (!left) {
69    ASSERT_FALSE(right);
70    return;
71  }
72  ASSERT_TRUE(right);
73
74  EXPECT_EQ(left->file_id(), right->file_id());
75  ExpectEquivalent(&left->details(), &right->details());
76}
77
78void ExpectEquivalent(const FileTracker* left, const FileTracker* right) {
79  if (!left) {
80    ASSERT_FALSE(right);
81    return;
82  }
83  ASSERT_TRUE(right);
84
85  EXPECT_EQ(left->tracker_id(), right->tracker_id());
86  EXPECT_EQ(left->parent_tracker_id(), right->parent_tracker_id());
87  EXPECT_EQ(left->file_id(), right->file_id());
88  EXPECT_EQ(left->app_id(), right->app_id());
89  EXPECT_EQ(left->is_app_root(), right->is_app_root());
90  ExpectEquivalent(&left->synced_details(), &right->synced_details());
91  EXPECT_EQ(left->dirty(), right->dirty());
92  EXPECT_EQ(left->active(), right->active());
93  EXPECT_EQ(left->needs_folder_listing(), right->needs_folder_listing());
94}
95
96template <typename Container>
97void ExpectEquivalentMaps(const Container& left, const Container& right);
98template <typename Key, typename Value, typename Compare>
99void ExpectEquivalent(const std::map<Key, Value, Compare>& left,
100                      const std::map<Key, Value, Compare>& right) {
101  ExpectEquivalentMaps(left, right);
102}
103
104template <typename Container>
105void ExpectEquivalentSets(const Container& left, const Container& right);
106template <typename Value, typename Compare>
107void ExpectEquivalent(const std::set<Value, Compare>& left,
108                      const std::set<Value, Compare>& right) {
109  return ExpectEquivalentSets(left, right);
110}
111
112void ExpectEquivalent(const TrackerSet& left,
113                      const TrackerSet& right) {
114  {
115    SCOPED_TRACE("Expect equivalent active_tracker");
116    ExpectEquivalent(left.active_tracker(), right.active_tracker());
117  }
118  ExpectEquivalent(left.tracker_set(), right.tracker_set());
119}
120
121template <typename Container>
122void ExpectEquivalentMaps(const Container& left, const Container& right) {
123  ASSERT_EQ(left.size(), right.size());
124
125  typedef typename Container::const_iterator const_iterator;
126  const_iterator left_itr = left.begin();
127  const_iterator right_itr = right.begin();
128  while (left_itr != left.end()) {
129    EXPECT_EQ(left_itr->first, right_itr->first);
130    ExpectEquivalent(left_itr->second, right_itr->second);
131    ++left_itr;
132    ++right_itr;
133  }
134}
135
136template <typename Container>
137void ExpectEquivalentSets(const Container& left, const Container& right) {
138  ASSERT_EQ(left.size(), right.size());
139
140  typedef typename Container::const_iterator const_iterator;
141  const_iterator left_itr = left.begin();
142  const_iterator right_itr = right.begin();
143  while (left_itr != left.end()) {
144    ExpectEquivalent(*left_itr, *right_itr);
145    ++left_itr;
146    ++right_itr;
147  }
148}
149
150void SyncStatusResultCallback(SyncStatusCode* status_out,
151                              SyncStatusCode status) {
152  EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
153  *status_out = status;
154}
155
156void DatabaseCreateResultCallback(SyncStatusCode* status_out,
157                                  scoped_ptr<MetadataDatabase>* database_out,
158                                  SyncStatusCode status,
159                                  scoped_ptr<MetadataDatabase> database) {
160  EXPECT_EQ(SYNC_STATUS_UNKNOWN, *status_out);
161  *status_out = status;
162  *database_out = database.Pass();
163}
164
165}  // namespace
166
167class MetadataDatabaseTest : public testing::Test {
168 public:
169  MetadataDatabaseTest()
170      : next_change_id_(kInitialChangeID + 1),
171        next_tracker_id_(kSyncRootTrackerID + 1),
172        next_file_id_number_(1),
173        next_md5_sequence_number_(1) {}
174
175  virtual ~MetadataDatabaseTest() {}
176
177  virtual void SetUp() OVERRIDE {
178    ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
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    TrackerSet trackers;
190    if (metadata_database_->FindTrackersByFileID(file_id, &trackers)) {
191      EXPECT_FALSE(trackers.empty());
192      return (*trackers.begin())->tracker_id();
193    }
194    return 0;
195  }
196
197  SyncStatusCode InitializeMetadataDatabase() {
198    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
199    MetadataDatabase::Create(base::MessageLoopProxy::current(),
200                             database_dir_.path(),
201                             base::Bind(&DatabaseCreateResultCallback,
202                                        &status, &metadata_database_));
203    message_loop_.RunUntilIdle();
204    return status;
205  }
206
207  void DropDatabase() {
208    metadata_database_.reset();
209    message_loop_.RunUntilIdle();
210  }
211
212  MetadataDatabase* metadata_database() { return metadata_database_.get(); }
213
214  leveldb::DB* db() {
215    if (!metadata_database_)
216      return NULL;
217    return metadata_database_->db_.get();
218  }
219
220  scoped_ptr<leveldb::DB> InitializeLevelDB() {
221    leveldb::DB* db = NULL;
222    leveldb::Options options;
223    options.create_if_missing = true;
224    options.max_open_files = 0;  // Use minimum.
225    leveldb::Status status =
226        leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
227    EXPECT_TRUE(status.ok());
228
229    db->Put(leveldb::WriteOptions(), "VERSION", base::Int64ToString(3));
230    SetUpServiceMetadata(db);
231
232    return make_scoped_ptr(db);
233  }
234
235  void SetUpServiceMetadata(leveldb::DB* db) {
236    ServiceMetadata service_metadata;
237    service_metadata.set_largest_change_id(kInitialChangeID);
238    service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
239    service_metadata.set_next_tracker_id(next_tracker_id_);
240    std::string value;
241    ASSERT_TRUE(service_metadata.SerializeToString(&value));
242    db->Put(leveldb::WriteOptions(), "SERVICE", value);
243  }
244
245  FileMetadata CreateSyncRootMetadata() {
246    FileMetadata sync_root;
247    sync_root.set_file_id(kSyncRootFolderID);
248    FileDetails* details = sync_root.mutable_details();
249    details->set_title("Chrome Syncable FileSystem");
250    details->set_file_kind(FILE_KIND_FOLDER);
251    return sync_root;
252  }
253
254  FileMetadata CreateFileMetadata(const FileMetadata& parent,
255                                  const std::string& title) {
256    FileMetadata file;
257    file.set_file_id(GenerateFileID());
258    FileDetails* details = file.mutable_details();
259    details->add_parent_folder_ids(parent.file_id());
260    details->set_title(title);
261    details->set_file_kind(FILE_KIND_FILE);
262    details->set_md5(
263        "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
264    return file;
265  }
266
267  FileMetadata CreateFolderMetadata(const FileMetadata& parent,
268                                    const std::string& title) {
269    FileMetadata folder;
270    folder.set_file_id(GenerateFileID());
271    FileDetails* details = folder.mutable_details();
272    details->add_parent_folder_ids(parent.file_id());
273    details->set_title(title);
274    details->set_file_kind(FILE_KIND_FOLDER);
275    return folder;
276  }
277
278  FileTracker CreateSyncRootTracker(const FileMetadata& sync_root) {
279    FileTracker sync_root_tracker;
280    sync_root_tracker.set_tracker_id(kSyncRootTrackerID);
281    sync_root_tracker.set_parent_tracker_id(0);
282    sync_root_tracker.set_file_id(sync_root.file_id());
283    sync_root_tracker.set_dirty(false);
284    sync_root_tracker.set_active(true);
285    sync_root_tracker.set_needs_folder_listing(false);
286    *sync_root_tracker.mutable_synced_details() = sync_root.details();
287    return sync_root_tracker;
288  }
289
290  FileTracker CreateTracker(const FileTracker& parent_tracker,
291                            const FileMetadata& file) {
292    FileTracker tracker;
293    tracker.set_tracker_id(next_tracker_id_++);
294    tracker.set_parent_tracker_id(parent_tracker.tracker_id());
295    tracker.set_file_id(file.file_id());
296    tracker.set_app_id(parent_tracker.app_id());
297    tracker.set_is_app_root(false);
298    tracker.set_dirty(false);
299    tracker.set_active(true);
300    tracker.set_needs_folder_listing(false);
301    *tracker.mutable_synced_details() = file.details();
302    return tracker;
303  }
304
305  scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
306      const FileMetadata& file) {
307    scoped_ptr<google_apis::ChangeResource> change(
308        new google_apis::ChangeResource);
309    change->set_change_id(file.details().change_id());
310    change->set_file_id(file.file_id());
311    change->set_deleted(file.details().deleted());
312    if (change->is_deleted())
313      return change.Pass();
314
315    scoped_ptr<google_apis::FileResource> file_resource(
316        new google_apis::FileResource);
317    ScopedVector<google_apis::ParentReference> parents;
318    for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
319      scoped_ptr<google_apis::ParentReference> parent(
320          new google_apis::ParentReference);
321      parent->set_file_id(file.details().parent_folder_ids(i));
322      parents.push_back(parent.release());
323    }
324
325    file_resource->set_file_id(file.file_id());
326    file_resource->set_parents(&parents);
327    file_resource->set_title(file.details().title());
328    if (file.details().file_kind() == FILE_KIND_FOLDER)
329      file_resource->set_mime_type("application/vnd.google-apps.folder");
330    else if (file.details().file_kind() == FILE_KIND_FILE)
331      file_resource->set_mime_type("text/plain");
332    else
333      file_resource->set_mime_type("application/vnd.google-apps.document");
334    file_resource->set_md5_checksum(file.details().md5());
335    file_resource->set_etag(file.details().etag());
336    file_resource->set_created_date(base::Time::FromInternalValue(
337        file.details().creation_time()));
338    file_resource->set_modified_date(base::Time::FromInternalValue(
339        file.details().modification_time()));
340
341    change->set_file(file_resource.Pass());
342    return change.Pass();
343  }
344
345  void ApplyRenameChangeToMetadata(const std::string& new_title,
346                                   FileMetadata* file) {
347    FileDetails* details = file->mutable_details();
348    details->set_title(new_title);
349    details->set_change_id(next_change_id_++);
350  }
351
352  void ApplyReorganizeChangeToMetadata(const std::string& new_parent,
353                                       FileMetadata* file) {
354    FileDetails* details = file->mutable_details();
355    details->clear_parent_folder_ids();
356    details->add_parent_folder_ids(new_parent);
357    details->set_change_id(next_change_id_++);
358  }
359
360  void ApplyContentChangeToMetadata(FileMetadata* file) {
361    FileDetails* details = file->mutable_details();
362    details->set_md5(
363        "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
364    details->set_change_id(next_change_id_++);
365  }
366
367  void PushToChangeList(scoped_ptr<google_apis::ChangeResource> change,
368                        ScopedVector<google_apis::ChangeResource>* changes) {
369    changes->push_back(change.release());
370  }
371
372  leveldb::Status PutFileToDB(leveldb::DB* db, const FileMetadata& file) {
373    std::string key = "FILE: " + file.file_id();
374    std::string value;
375    file.SerializeToString(&value);
376    return db->Put(leveldb::WriteOptions(), key, value);
377  }
378
379  leveldb::Status PutTrackerToDB(leveldb::DB* db,
380                                 const FileTracker& tracker) {
381    std::string key = "TRACKER: " + base::Int64ToString(tracker.tracker_id());
382    std::string value;
383    tracker.SerializeToString(&value);
384    return db->Put(leveldb::WriteOptions(), key, value);
385  }
386
387  void VerifyReloadConsistency() {
388    scoped_ptr<MetadataDatabase> metadata_database_2;
389    ASSERT_EQ(SYNC_STATUS_OK,
390              MetadataDatabase::CreateForTesting(
391                  metadata_database_->db_.Pass(),
392                  &metadata_database_2));
393    metadata_database_->db_ = metadata_database_2->db_.Pass();
394
395    {
396      SCOPED_TRACE("Expect equivalent service_metadata");
397      ExpectEquivalent(metadata_database_->service_metadata_.get(),
398                       metadata_database_2->service_metadata_.get());
399    }
400
401    {
402      SCOPED_TRACE("Expect equivalent file_by_id_ contents.");
403      ExpectEquivalent(metadata_database_->file_by_id_,
404                       metadata_database_2->file_by_id_);
405    }
406
407    {
408      SCOPED_TRACE("Expect equivalent tracker_by_id_ contents.");
409      ExpectEquivalent(metadata_database_->tracker_by_id_,
410                       metadata_database_2->tracker_by_id_);
411    }
412
413    {
414      SCOPED_TRACE("Expect equivalent trackers_by_file_id_ contents.");
415      ExpectEquivalent(metadata_database_->trackers_by_file_id_,
416                       metadata_database_2->trackers_by_file_id_);
417    }
418
419    {
420      SCOPED_TRACE("Expect equivalent app_root_by_app_id_ contents.");
421      ExpectEquivalent(metadata_database_->app_root_by_app_id_,
422                       metadata_database_2->app_root_by_app_id_);
423    }
424
425    {
426      SCOPED_TRACE("Expect equivalent trackers_by_parent_and_title_ contents.");
427      ExpectEquivalent(metadata_database_->trackers_by_parent_and_title_,
428                       metadata_database_2->trackers_by_parent_and_title_);
429    }
430
431    {
432      SCOPED_TRACE("Expect equivalent dirty_trackers_ contents.");
433      ExpectEquivalent(metadata_database_->dirty_trackers_,
434                       metadata_database_2->dirty_trackers_);
435    }
436  }
437
438  void VerifyFile(const FileMetadata& file) {
439    FileMetadata file_in_metadata_database;
440    ASSERT_TRUE(metadata_database()->FindFileByFileID(
441        file.file_id(), &file_in_metadata_database));
442
443    SCOPED_TRACE("Expect equivalent " + file.file_id());
444    ExpectEquivalent(&file, &file_in_metadata_database);
445  }
446
447  void VerifyTracker(const FileTracker& tracker) {
448    FileTracker tracker_in_metadata_database;
449    ASSERT_TRUE(metadata_database()->FindTrackerByTrackerID(
450        tracker.tracker_id(), &tracker_in_metadata_database));
451
452    SCOPED_TRACE("Expect equivalent tracker[" +
453                 base::Int64ToString(tracker.tracker_id()) + "]");
454    ExpectEquivalent(&tracker, &tracker_in_metadata_database);
455  }
456
457  SyncStatusCode RegisterApp(const std::string& app_id,
458                             const std::string& folder_id) {
459    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
460    metadata_database_->RegisterApp(
461        app_id, folder_id,
462        base::Bind(&SyncStatusResultCallback, &status));
463    message_loop_.RunUntilIdle();
464    return status;
465  }
466
467  SyncStatusCode DisableApp(const std::string& app_id) {
468    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
469    metadata_database_->DisableApp(
470        app_id, base::Bind(&SyncStatusResultCallback, &status));
471    message_loop_.RunUntilIdle();
472    return status;
473  }
474
475  SyncStatusCode EnableApp(const std::string& app_id) {
476    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
477    metadata_database_->EnableApp(
478        app_id, base::Bind(&SyncStatusResultCallback, &status));
479    message_loop_.RunUntilIdle();
480    return status;
481  }
482
483  SyncStatusCode UnregisterApp(const std::string& app_id) {
484    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
485    metadata_database_->UnregisterApp(
486        app_id, base::Bind(&SyncStatusResultCallback, &status));
487    message_loop_.RunUntilIdle();
488    return status;
489  }
490
491  SyncStatusCode UpdateByChangeList(
492      ScopedVector<google_apis::ChangeResource> changes) {
493    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
494    metadata_database_->UpdateByChangeList(
495        changes.Pass(), base::Bind(&SyncStatusResultCallback, &status));
496    message_loop_.RunUntilIdle();
497    return status;
498  }
499
500 private:
501  base::ScopedTempDir database_dir_;
502  base::MessageLoop message_loop_;
503
504  scoped_ptr<MetadataDatabase> metadata_database_;
505
506  int64 next_change_id_;
507  int64 next_tracker_id_;
508  int64 next_file_id_number_;
509  int64 next_md5_sequence_number_;
510
511  DISALLOW_COPY_AND_ASSIGN(MetadataDatabaseTest);
512};
513
514TEST_F(MetadataDatabaseTest, InitializationTest_Empty) {
515  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
516  DropDatabase();
517  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
518}
519
520TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) {
521  FileMetadata sync_root(CreateSyncRootMetadata());
522  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
523
524  FileMetadata app_root(
525      CreateFolderMetadata(sync_root, "app_id" /* title */));
526  FileTracker app_root_tracker(
527      CreateTracker(sync_root_tracker, app_root));
528  app_root_tracker.set_app_id(app_root.details().title());
529  app_root_tracker.set_is_app_root(true);
530
531  FileMetadata file(CreateFileMetadata(app_root, "file"));
532  FileTracker file_tracker(CreateTracker(app_root_tracker, file));
533
534  FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
535  FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
536
537  FileMetadata file_in_folder(
538      CreateFileMetadata(folder, "file_in_folder"));
539  FileTracker file_in_folder_tracker(
540      CreateTracker(folder_tracker, file_in_folder));
541
542  FileMetadata orphaned_file(
543      CreateFileMetadata(sync_root, "orphaned_file"));
544  orphaned_file.mutable_details()->clear_parent_folder_ids();
545  FileTracker orphaned_file_tracker(
546      CreateTracker(sync_root_tracker, orphaned_file));
547  orphaned_file_tracker.set_parent_tracker_id(0);
548
549  {
550    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
551    ASSERT_TRUE(db);
552
553    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
554    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
555    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
556    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
557    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
558    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
559    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
560    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
561    EXPECT_TRUE(PutFileToDB(db.get(), file_in_folder).ok());
562    EXPECT_TRUE(PutTrackerToDB(db.get(), file_in_folder_tracker).ok());
563    EXPECT_TRUE(PutFileToDB(db.get(), orphaned_file).ok());
564    EXPECT_TRUE(PutTrackerToDB(db.get(), orphaned_file_tracker).ok());
565  }
566
567  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
568
569  VerifyFile(sync_root);
570  VerifyTracker(sync_root_tracker);
571  VerifyFile(app_root);
572  VerifyTracker(app_root_tracker);
573  VerifyFile(file);
574  VerifyTracker(file_tracker);
575  VerifyFile(folder);
576  VerifyTracker(folder_tracker);
577  VerifyFile(file_in_folder);
578  VerifyTracker(file_in_folder_tracker);
579
580  EXPECT_FALSE(metadata_database()->FindFileByFileID(
581      orphaned_file.file_id(), NULL));
582  EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
583      orphaned_file_tracker.tracker_id(), NULL));
584}
585
586TEST_F(MetadataDatabaseTest, AppManagementTest) {
587  FileMetadata sync_root(CreateSyncRootMetadata());
588  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
589
590  FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
591  FileTracker app_root_tracker(
592      CreateTracker(sync_root_tracker, app_root));
593  app_root_tracker.set_app_id(app_root.details().title());
594  app_root_tracker.set_is_app_root(true);
595
596  FileMetadata file(CreateFileMetadata(app_root, "file"));
597  FileTracker file_tracker(CreateTracker(app_root_tracker, file));
598
599  FileMetadata folder(CreateFolderMetadata(sync_root, "folder"));
600  FileTracker folder_tracker(CreateTracker(sync_root_tracker, folder));
601  folder_tracker.set_active(false);
602
603  {
604    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
605    ASSERT_TRUE(db);
606
607    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
608    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
609    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
610    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
611    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
612    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
613    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
614    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
615  }
616
617  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
618  VerifyFile(sync_root);
619  VerifyTracker(sync_root_tracker);
620  VerifyFile(app_root);
621  VerifyTracker(app_root_tracker);
622  VerifyFile(file);
623  VerifyTracker(file_tracker);
624  VerifyFile(folder);
625  VerifyTracker(folder_tracker);
626
627  folder_tracker.set_app_id("foo");
628  folder_tracker.set_is_app_root(true);
629  folder_tracker.set_active(true);
630  folder_tracker.set_dirty(true);
631  folder_tracker.set_needs_folder_listing(true);
632  EXPECT_EQ(SYNC_STATUS_OK, RegisterApp(
633      folder_tracker.app_id(), folder.file_id()));
634  VerifyFile(folder);
635  VerifyTracker(folder_tracker);
636  VerifyReloadConsistency();
637
638  EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder_tracker.app_id()));
639  folder_tracker.set_active(false);
640  VerifyFile(folder);
641  VerifyTracker(folder_tracker);
642  VerifyReloadConsistency();
643
644  EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder_tracker.app_id()));
645  folder_tracker.set_active(true);
646  VerifyFile(folder);
647  VerifyTracker(folder_tracker);
648  VerifyReloadConsistency();
649
650  EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder_tracker.app_id()));
651  folder_tracker.set_app_id(std::string());
652  folder_tracker.set_is_app_root(false);
653  folder_tracker.set_active(false);
654  VerifyFile(folder);
655  VerifyTracker(folder_tracker);
656  VerifyReloadConsistency();
657
658  EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(app_root_tracker.app_id()));
659  app_root_tracker.set_app_id(std::string());
660  app_root_tracker.set_is_app_root(false);
661  app_root_tracker.set_active(false);
662  app_root_tracker.set_dirty(true);
663  VerifyFile(app_root);
664  VerifyTracker(app_root_tracker);
665  EXPECT_FALSE(metadata_database()->FindFileByFileID(file.file_id(), NULL));
666  EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
667      file_tracker.tracker_id(), NULL));
668  VerifyReloadConsistency();
669}
670
671TEST_F(MetadataDatabaseTest, BuildPathTest) {
672  FileMetadata sync_root(CreateSyncRootMetadata());
673  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
674
675  FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
676  FileTracker app_root_tracker(
677      CreateTracker(sync_root_tracker, app_root));
678  app_root_tracker.set_app_id(app_root.details().title());
679  app_root_tracker.set_is_app_root(true);
680
681  FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
682  FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
683
684  FileMetadata file(CreateFolderMetadata(folder, "file"));
685  FileTracker file_tracker(CreateTracker(folder_tracker, file));
686
687  FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder"));
688  FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
689                                                          inactive_folder));
690  inactive_folder_tracker.set_active(false);
691
692  {
693    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
694    ASSERT_TRUE(db);
695
696    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
697    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
698    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
699    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
700    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
701    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
702    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
703    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
704  }
705
706  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
707
708  base::FilePath path;
709  EXPECT_FALSE(metadata_database()->BuildPathForTracker(
710      sync_root_tracker.tracker_id(), &path));
711  EXPECT_TRUE(metadata_database()->BuildPathForTracker(
712      app_root_tracker.tracker_id(), &path));
713  EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(), path);
714  EXPECT_TRUE(metadata_database()->BuildPathForTracker(
715      file_tracker.tracker_id(), &path));
716  EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(),
717            path);
718}
719
720TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
721  FileMetadata sync_root(CreateSyncRootMetadata());
722  FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
723
724  FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
725  FileTracker app_root_tracker(
726      CreateTracker(sync_root_tracker, app_root));
727
728  FileMetadata disabled_app_root(
729      CreateFolderMetadata(sync_root, "disabled_app"));
730  FileTracker disabled_app_root_tracker(
731      CreateTracker(sync_root_tracker, disabled_app_root));
732
733  FileMetadata file(CreateFileMetadata(app_root, "file"));
734  FileTracker file_tracker(CreateTracker(app_root_tracker, file));
735
736  FileMetadata renamed_file(CreateFileMetadata(app_root, "to be renamed"));
737  FileTracker renamed_file_tracker(
738      CreateTracker(app_root_tracker, renamed_file));
739
740  FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
741  FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
742
743  FileMetadata reorganized_file(
744      CreateFileMetadata(app_root, "to be reorganized"));
745  FileTracker reorganized_file_tracker(
746      CreateTracker(app_root_tracker, reorganized_file));
747
748  FileMetadata updated_file(CreateFileMetadata(app_root, "to be updated"));
749  FileTracker updated_file_tracker(
750      CreateTracker(app_root_tracker, updated_file));
751
752  FileMetadata noop_file(CreateFileMetadata(app_root, "have noop change"));
753  FileTracker noop_file_tracker(
754      CreateTracker(app_root_tracker, noop_file));
755
756  FileMetadata new_file(CreateFileMetadata(app_root, "to be added later"));
757
758  {
759    scoped_ptr<leveldb::DB> db = InitializeLevelDB();
760    ASSERT_TRUE(db);
761
762    EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
763    EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
764    EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
765    EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
766    EXPECT_TRUE(PutFileToDB(db.get(), disabled_app_root).ok());
767    EXPECT_TRUE(PutTrackerToDB(db.get(), disabled_app_root_tracker).ok());
768    EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
769    EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
770    EXPECT_TRUE(PutFileToDB(db.get(), renamed_file).ok());
771    EXPECT_TRUE(PutTrackerToDB(db.get(), renamed_file_tracker).ok());
772    EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
773    EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
774    EXPECT_TRUE(PutFileToDB(db.get(), reorganized_file).ok());
775    EXPECT_TRUE(PutTrackerToDB(db.get(), reorganized_file_tracker).ok());
776    EXPECT_TRUE(PutFileToDB(db.get(), updated_file).ok());
777    EXPECT_TRUE(PutTrackerToDB(db.get(), updated_file_tracker).ok());
778    EXPECT_TRUE(PutFileToDB(db.get(), noop_file).ok());
779    EXPECT_TRUE(PutTrackerToDB(db.get(), noop_file_tracker).ok());
780  }
781
782  EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
783
784  ApplyRenameChangeToMetadata("renamed", &renamed_file);
785  ApplyReorganizeChangeToMetadata(folder.file_id(), &reorganized_file);
786  ApplyContentChangeToMetadata(&updated_file);
787
788  ScopedVector<google_apis::ChangeResource> changes;
789  PushToChangeList(CreateChangeResourceFromMetadata(renamed_file), &changes);
790  PushToChangeList(CreateChangeResourceFromMetadata(
791      reorganized_file), &changes);
792  PushToChangeList(CreateChangeResourceFromMetadata(updated_file), &changes);
793  PushToChangeList(CreateChangeResourceFromMetadata(noop_file), &changes);
794  PushToChangeList(CreateChangeResourceFromMetadata(new_file), &changes);
795
796  renamed_file_tracker.set_dirty(true);
797  reorganized_file_tracker.set_dirty(true);
798  updated_file_tracker.set_dirty(true);
799  noop_file_tracker.set_dirty(true);
800
801  EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass()));
802
803  FileTracker new_file_tracker(CreateTracker(app_root_tracker, new_file));
804  new_file_tracker.set_tracker_id(GetTrackerIDByFileID(new_file.file_id()));
805  new_file_tracker.clear_synced_details();
806  new_file_tracker.set_active(false);
807  new_file_tracker.set_dirty(true);
808  EXPECT_NE(0, new_file_tracker.tracker_id());
809
810  VerifyFile(sync_root);
811  VerifyTracker(sync_root_tracker);
812  VerifyFile(app_root);
813  VerifyTracker(app_root_tracker);
814  VerifyFile(disabled_app_root);
815  VerifyTracker(disabled_app_root_tracker);
816  VerifyFile(file);
817  VerifyTracker(file_tracker);
818  VerifyFile(renamed_file);
819  VerifyTracker(renamed_file_tracker);
820  VerifyFile(folder);
821  VerifyTracker(folder_tracker);
822  VerifyFile(reorganized_file);
823  VerifyTracker(reorganized_file_tracker);
824  VerifyFile(updated_file);
825  VerifyTracker(updated_file_tracker);
826  VerifyFile(noop_file);
827  VerifyTracker(noop_file_tracker);
828  VerifyFile(new_file);
829  VerifyTracker(new_file_tracker);
830
831  VerifyReloadConsistency();
832}
833
834}  // namespace drive_backend
835}  // namespace sync_file_system
836