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