1// Copyright 2014 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_index.h"
6
7#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
8#include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
9#include "chrome/browser/sync_file_system/drive_backend/leveldb_wrapper.h"
10#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
11#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
12#include "testing/gtest/include/gtest/gtest.h"
13#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
14#include "third_party/leveldatabase/src/include/leveldb/db.h"
15#include "third_party/leveldatabase/src/include/leveldb/env.h"
16
17namespace sync_file_system {
18namespace drive_backend {
19
20namespace {
21
22const int64 kSyncRootTrackerID = 1;
23const int64 kAppRootTrackerID = 2;
24const int64 kFileTrackerID = 3;
25const int64 kPlaceholderTrackerID = 4;
26
27scoped_ptr<DatabaseContents> CreateTestDatabaseContents() {
28  scoped_ptr<DatabaseContents> contents(new DatabaseContents);
29
30  scoped_ptr<FileMetadata> sync_root_metadata =
31      test_util::CreateFolderMetadata("sync_root_folder_id",
32                                      "Chrome Syncable FileSystem");
33  scoped_ptr<FileTracker> sync_root_tracker =
34      test_util::CreateTracker(*sync_root_metadata, kSyncRootTrackerID, NULL);
35
36  scoped_ptr<FileMetadata> app_root_metadata =
37      test_util::CreateFolderMetadata("app_root_folder_id", "app_id");
38  scoped_ptr<FileTracker> app_root_tracker =
39      test_util::CreateTracker(*app_root_metadata, kAppRootTrackerID,
40                               sync_root_tracker.get());
41  app_root_tracker->set_app_id("app_id");
42  app_root_tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT);
43
44  scoped_ptr<FileMetadata> file_metadata =
45      test_util::CreateFileMetadata("file_id", "file", "file_md5");
46  scoped_ptr<FileTracker> file_tracker =
47      test_util::CreateTracker(*file_metadata, kFileTrackerID,
48                               app_root_tracker.get());
49
50  scoped_ptr<FileTracker> placeholder_tracker =
51      test_util::CreatePlaceholderTracker("unsynced_file_id",
52                                          kPlaceholderTrackerID,
53                                          app_root_tracker.get());
54
55  contents->file_metadata.push_back(sync_root_metadata.release());
56  contents->file_trackers.push_back(sync_root_tracker.release());
57  contents->file_metadata.push_back(app_root_metadata.release());
58  contents->file_trackers.push_back(app_root_tracker.release());
59  contents->file_metadata.push_back(file_metadata.release());
60  contents->file_trackers.push_back(file_tracker.release());
61  contents->file_trackers.push_back(placeholder_tracker.release());
62  return contents.Pass();
63}
64
65}  // namespace
66
67class MetadataDatabaseIndexTest : public testing::Test {
68 public:
69  virtual void SetUp() OVERRIDE {
70    in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
71    InitializeLevelDB();
72
73    contents_ = CreateTestDatabaseContents();
74    index_ = MetadataDatabaseIndex::CreateForTesting(contents_.get(),
75                                                     db_.get());
76  }
77
78  MetadataDatabaseIndex* index() { return index_.get(); }
79
80 private:
81  void InitializeLevelDB() {
82    leveldb::DB* db = NULL;
83    leveldb::Options options;
84    options.create_if_missing = true;
85    options.max_open_files = 0;  // Use minimum.
86    options.env = in_memory_env_.get();
87    leveldb::Status status = leveldb::DB::Open(options, "", &db);
88    ASSERT_TRUE(status.ok());
89
90    db_.reset(new LevelDBWrapper(make_scoped_ptr(db)));
91  }
92
93  scoped_ptr<DatabaseContents> contents_;
94  scoped_ptr<MetadataDatabaseIndex> index_;
95
96  scoped_ptr<leveldb::Env> in_memory_env_;
97  scoped_ptr<LevelDBWrapper> db_;
98};
99
100TEST_F(MetadataDatabaseIndexTest, GetEntryTest) {
101  FileTracker tracker;
102  EXPECT_FALSE(index()->GetFileTracker(kInvalidTrackerID, NULL));
103  ASSERT_TRUE(index()->GetFileTracker(kFileTrackerID, &tracker));
104  EXPECT_EQ(kFileTrackerID, tracker.tracker_id());
105  EXPECT_EQ("file_id", tracker.file_id());
106
107  FileMetadata metadata;
108  EXPECT_FALSE(index()->GetFileMetadata(std::string(), NULL));
109  ASSERT_TRUE(index()->GetFileMetadata("file_id", &metadata));
110  EXPECT_EQ("file_id", metadata.file_id());
111}
112
113TEST_F(MetadataDatabaseIndexTest, IndexLookUpTest) {
114  TrackerIDSet trackers = index()->GetFileTrackerIDsByFileID("file_id");
115  EXPECT_EQ(1u, trackers.size());
116  EXPECT_TRUE(trackers.has_active());
117  EXPECT_EQ(kFileTrackerID, trackers.active_tracker());
118
119  int64 app_root_tracker_id = index()->GetAppRootTracker("app_id");
120  EXPECT_EQ(kAppRootTrackerID, app_root_tracker_id);
121
122  trackers = index()->GetFileTrackerIDsByParentAndTitle(
123      app_root_tracker_id, "file");
124  EXPECT_EQ(1u, trackers.size());
125  EXPECT_TRUE(trackers.has_active());
126  EXPECT_EQ(kFileTrackerID, trackers.active_tracker());
127
128  EXPECT_TRUE(index()->PickMultiTrackerFileID().empty());
129  EXPECT_EQ(kInvalidTrackerID,
130            index()->PickMultiBackingFilePath().parent_id);
131  EXPECT_EQ(kPlaceholderTrackerID, index()->PickDirtyTracker());
132}
133
134TEST_F(MetadataDatabaseIndexTest, UpdateTest) {
135  index()->DemoteDirtyTracker(kPlaceholderTrackerID);
136  EXPECT_EQ(kInvalidTrackerID, index()->PickDirtyTracker());
137  index()->PromoteDemotedDirtyTrackers();
138  EXPECT_EQ(kPlaceholderTrackerID, index()->PickDirtyTracker());
139
140  FileMetadata metadata;
141  ASSERT_TRUE(index()->GetFileMetadata("file_id", &metadata));
142  FileTracker app_root_tracker;
143  ASSERT_TRUE(index()->GetFileTracker(kAppRootTrackerID, &app_root_tracker));
144
145  int64 new_tracker_id = 100;
146  scoped_ptr<FileTracker> new_tracker =
147      test_util::CreateTracker(metadata, new_tracker_id, &app_root_tracker);
148  new_tracker->set_active(false);
149  index()->StoreFileTracker(new_tracker.Pass());
150
151  EXPECT_EQ("file_id", index()->PickMultiTrackerFileID());
152  EXPECT_EQ(ParentIDAndTitle(kAppRootTrackerID, std::string("file")),
153            index()->PickMultiBackingFilePath());
154
155  index()->RemoveFileMetadata("file_id");
156  index()->RemoveFileTracker(kFileTrackerID);
157
158  EXPECT_FALSE(index()->GetFileMetadata("file_id", NULL));
159  EXPECT_FALSE(index()->GetFileTracker(kFileTrackerID, NULL));
160}
161
162}  // namespace drive_backend
163}  // namespace sync_file_system
164