register_app_task_unittest.cc revision 010d83a9304c5a91596085d917d248abff47903a
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/register_app_task.h"
6
7#include <vector>
8
9#include "base/files/scoped_temp_dir.h"
10#include "base/format_macros.h"
11#include "base/run_loop.h"
12#include "base/strings/string_number_conversions.h"
13#include "base/strings/stringprintf.h"
14#include "chrome/browser/drive/drive_uploader.h"
15#include "chrome/browser/drive/fake_drive_service.h"
16#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
17#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
18#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
19#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
20#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
21#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
22#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
23#include "content/public/test/test_browser_thread_bundle.h"
24#include "google_apis/drive/gdata_wapi_parser.h"
25#include "testing/gtest/include/gtest/gtest.h"
26#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
27#include "third_party/leveldatabase/src/include/leveldb/db.h"
28#include "third_party/leveldatabase/src/include/leveldb/env.h"
29#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
30
31namespace sync_file_system {
32namespace drive_backend {
33
34namespace {
35const int64 kSyncRootTrackerID = 100;
36}  // namespace
37
38class RegisterAppTaskTest : public testing::Test {
39 public:
40  RegisterAppTaskTest()
41      : next_file_id_(1000),
42        next_tracker_id_(10000) {}
43  virtual ~RegisterAppTaskTest() {}
44
45  virtual void SetUp() OVERRIDE {
46    ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
47    in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
48
49    scoped_ptr<drive::FakeDriveService>
50        fake_drive_service(new drive::FakeDriveService);
51    scoped_ptr<drive::DriveUploaderInterface>
52        drive_uploader(new drive::DriveUploader(
53            fake_drive_service.get(),
54            base::MessageLoopProxy::current()));
55
56    fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
57        fake_drive_service.get(), drive_uploader.get(),
58        kSyncRootFolderTitle));
59
60    context_.reset(
61        new SyncEngineContext(
62            fake_drive_service.PassAs<drive::DriveServiceInterface>(),
63            drive_uploader.Pass(),
64            base::MessageLoopProxy::current(),
65            base::MessageLoopProxy::current(),
66            base::MessageLoopProxy::current()));
67
68    ASSERT_EQ(google_apis::HTTP_CREATED,
69              fake_drive_service_helper_->AddOrphanedFolder(
70                  kSyncRootFolderTitle, &sync_root_folder_id_));
71  }
72
73  virtual void TearDown() OVERRIDE {
74    context_.reset();
75    base::RunLoop().RunUntilIdle();
76  }
77
78 protected:
79  scoped_ptr<leveldb::DB> OpenLevelDB() {
80    leveldb::DB* db = NULL;
81    leveldb::Options options;
82    options.create_if_missing = true;
83    options.env = in_memory_env_.get();
84    leveldb::Status status =
85        leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
86    EXPECT_TRUE(status.ok());
87    return make_scoped_ptr<leveldb::DB>(db);
88  }
89
90  void SetUpInitialData(leveldb::DB* db) {
91    ServiceMetadata service_metadata;
92    service_metadata.set_largest_change_id(100);
93    service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
94    service_metadata.set_next_tracker_id(next_tracker_id_);
95
96    FileDetails sync_root_details;
97    sync_root_details.set_title(kSyncRootFolderTitle);
98    sync_root_details.set_file_kind(FILE_KIND_FOLDER);
99    sync_root_details.set_change_id(1);
100
101    FileMetadata sync_root_metadata;
102    sync_root_metadata.set_file_id(sync_root_folder_id_);
103    *sync_root_metadata.mutable_details() = sync_root_details;
104
105    FileTracker sync_root_tracker;
106    sync_root_tracker.set_tracker_id(service_metadata.sync_root_tracker_id());
107    sync_root_tracker.set_parent_tracker_id(0);
108    sync_root_tracker.set_file_id(sync_root_metadata.file_id());
109    sync_root_tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
110    *sync_root_tracker.mutable_synced_details() = sync_root_details;
111    sync_root_tracker.set_active(true);
112
113    leveldb::WriteBatch batch;
114    batch.Put(kDatabaseVersionKey,
115              base::Int64ToString(kCurrentDatabaseVersion));
116    PutServiceMetadataToBatch(service_metadata, &batch);
117    PutFileMetadataToBatch(sync_root_metadata, &batch);
118    PutFileTrackerToBatch(sync_root_tracker, &batch);
119    EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
120  }
121
122  void CreateMetadataDatabase(scoped_ptr<leveldb::DB> db) {
123    ASSERT_TRUE(db);
124    ASSERT_FALSE(context_->GetMetadataDatabase());
125    scoped_ptr<MetadataDatabase> metadata_db;
126    ASSERT_EQ(SYNC_STATUS_OK,
127              MetadataDatabase::CreateForTesting(
128                  db.Pass(), &metadata_db));
129    context_->SetMetadataDatabase(metadata_db.Pass());
130  }
131
132  SyncStatusCode RunRegisterAppTask(const std::string& app_id) {
133    RegisterAppTask task(context_.get(), app_id);
134    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
135    task.RunExclusive(CreateResultReceiver(&status));
136    base::RunLoop().RunUntilIdle();
137    return status;
138  }
139
140  void SetUpRegisteredAppRoot(
141      const std::string& app_id,
142      leveldb::DB* db) {
143    FileDetails details;
144    details.set_title(app_id);
145    details.set_file_kind(FILE_KIND_FOLDER);
146    details.add_parent_folder_ids(sync_root_folder_id_);
147
148    FileMetadata metadata;
149    metadata.set_file_id(GenerateFileID());
150    *metadata.mutable_details() = details;
151
152    FileTracker tracker;
153    tracker.set_parent_tracker_id(kSyncRootTrackerID);
154    tracker.set_tracker_id(next_tracker_id_++);
155    tracker.set_file_id(metadata.file_id());
156    tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
157    tracker.set_app_id(app_id);
158    *tracker.mutable_synced_details() = details;
159    tracker.set_active(true);
160
161    leveldb::WriteBatch batch;
162    PutFileMetadataToBatch(metadata, &batch);
163    PutFileTrackerToBatch(tracker, &batch);
164    EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
165  }
166
167  void SetUpUnregisteredAppRoot(const std::string& app_id,
168                                leveldb::DB* db) {
169    FileDetails details;
170    details.set_title(app_id);
171    details.set_file_kind(FILE_KIND_FOLDER);
172    details.add_parent_folder_ids(sync_root_folder_id_);
173
174    FileMetadata metadata;
175    metadata.set_file_id(GenerateFileID());
176    *metadata.mutable_details() = details;
177
178    FileTracker tracker;
179    tracker.set_parent_tracker_id(kSyncRootTrackerID);
180    tracker.set_tracker_id(next_tracker_id_++);
181    tracker.set_file_id(metadata.file_id());
182    tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
183    *tracker.mutable_synced_details() = details;
184    tracker.set_active(false);
185
186    leveldb::WriteBatch batch;
187    PutFileMetadataToBatch(metadata, &batch);
188    PutFileTrackerToBatch(tracker, &batch);
189    EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
190  }
191
192  size_t CountRegisteredAppRoot() {
193    std::vector<std::string> app_ids;
194    context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
195    return app_ids.size();
196  }
197
198  bool IsAppRegistered(const std::string& app_id) {
199    TrackerIDSet trackers;
200    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
201            kSyncRootTrackerID, app_id, &trackers))
202      return false;
203    return trackers.has_active();
204  }
205
206  size_t CountRemoteFileInSyncRoot() {
207    ScopedVector<google_apis::ResourceEntry> files;
208    EXPECT_EQ(google_apis::HTTP_SUCCESS,
209              fake_drive_service_helper_->ListFilesInFolder(
210                  sync_root_folder_id_, &files));
211    return files.size();
212  }
213
214  bool HasRemoteAppRoot(const std::string& app_id) {
215    TrackerIDSet files;
216    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
217            kSyncRootTrackerID, app_id, &files) ||
218        !files.has_active())
219      return false;
220
221    FileTracker app_root_tracker;
222    EXPECT_TRUE(context_->GetMetadataDatabase()->FindTrackerByTrackerID(
223        files.active_tracker(), &app_root_tracker));
224    std::string app_root_folder_id = app_root_tracker.file_id();
225    scoped_ptr<google_apis::ResourceEntry> entry;
226    if (google_apis::HTTP_SUCCESS !=
227        fake_drive_service_helper_->GetResourceEntry(
228            app_root_folder_id, &entry))
229      return false;
230
231    return !entry->deleted();
232  }
233
234 private:
235  std::string GenerateFileID() {
236    return base::StringPrintf("file_id_%" PRId64, next_file_id_++);
237  }
238
239  scoped_ptr<leveldb::Env> in_memory_env_;
240
241  std::string sync_root_folder_id_;
242
243  int64 next_file_id_;
244  int64 next_tracker_id_;
245
246  content::TestBrowserThreadBundle browser_threads_;
247  base::ScopedTempDir database_dir_;
248
249  scoped_ptr<SyncEngineContext> context_;
250  scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
251
252  DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest);
253};
254
255TEST_F(RegisterAppTaskTest, AlreadyRegistered) {
256  scoped_ptr<leveldb::DB> db(OpenLevelDB());
257  ASSERT_TRUE(db);
258  SetUpInitialData(db.get());
259
260  const std::string kAppID = "app_id";
261  SetUpRegisteredAppRoot(kAppID, db.get());
262
263  CreateMetadataDatabase(db.Pass());
264  EXPECT_EQ(SYNC_STATUS_OK, RunRegisterAppTask(kAppID));
265
266  EXPECT_EQ(1u, CountRegisteredAppRoot());
267  EXPECT_TRUE(IsAppRegistered(kAppID));
268}
269
270TEST_F(RegisterAppTaskTest, CreateAppFolder) {
271  scoped_ptr<leveldb::DB> db(OpenLevelDB());
272  ASSERT_TRUE(db);
273  SetUpInitialData(db.get());
274
275  const std::string kAppID = "app_id";
276  CreateMetadataDatabase(db.Pass());
277  RunRegisterAppTask(kAppID);
278
279  EXPECT_EQ(1u, CountRegisteredAppRoot());
280  EXPECT_TRUE(IsAppRegistered(kAppID));
281
282  EXPECT_EQ(1u, CountRemoteFileInSyncRoot());
283  EXPECT_TRUE(HasRemoteAppRoot(kAppID));
284}
285
286TEST_F(RegisterAppTaskTest, RegisterExistingFolder) {
287  scoped_ptr<leveldb::DB> db(OpenLevelDB());
288  ASSERT_TRUE(db);
289  SetUpInitialData(db.get());
290
291  const std::string kAppID = "app_id";
292  SetUpUnregisteredAppRoot(kAppID, db.get());
293
294  CreateMetadataDatabase(db.Pass());
295  RunRegisterAppTask(kAppID);
296
297  EXPECT_EQ(1u, CountRegisteredAppRoot());
298  EXPECT_TRUE(IsAppRegistered(kAppID));
299}
300
301TEST_F(RegisterAppTaskTest, RegisterExistingFolder_MultipleCandidate) {
302  scoped_ptr<leveldb::DB> db(OpenLevelDB());
303  ASSERT_TRUE(db);
304  SetUpInitialData(db.get());
305
306  const std::string kAppID = "app_id";
307  SetUpUnregisteredAppRoot(kAppID, db.get());
308  SetUpUnregisteredAppRoot(kAppID, db.get());
309
310  CreateMetadataDatabase(db.Pass());
311  RunRegisterAppTask(kAppID);
312
313  EXPECT_EQ(1u, CountRegisteredAppRoot());
314  EXPECT_TRUE(IsAppRegistered(kAppID));
315}
316
317}  // namespace drive_backend
318}  // namespace sync_file_system
319