register_app_task_unittest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 "base/thread_task_runner_handle.h"
15#include "chrome/browser/drive/drive_uploader.h"
16#include "chrome/browser/drive/fake_drive_service.h"
17#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
18#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
19#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
20#include "chrome/browser/sync_file_system/drive_backend/leveldb_wrapper.h"
21#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
22#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
23#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
24#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
25#include "content/public/test/test_browser_thread_bundle.h"
26#include "google_apis/drive/drive_api_parser.h"
27#include "testing/gtest/include/gtest/gtest.h"
28#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
29#include "third_party/leveldatabase/src/include/leveldb/db.h"
30#include "third_party/leveldatabase/src/include/leveldb/env.h"
31
32namespace sync_file_system {
33namespace drive_backend {
34
35namespace {
36const int64 kSyncRootTrackerID = 100;
37}  // namespace
38
39class RegisterAppTaskTest : public testing::Test {
40 public:
41  RegisterAppTaskTest()
42      : next_file_id_(1000),
43        next_tracker_id_(10000) {}
44  virtual ~RegisterAppTaskTest() {}
45
46  virtual void SetUp() OVERRIDE {
47    ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
48    in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
49
50    scoped_ptr<drive::FakeDriveService>
51        fake_drive_service(new drive::FakeDriveService);
52    scoped_ptr<drive::DriveUploaderInterface>
53        drive_uploader(new drive::DriveUploader(
54            fake_drive_service.get(),
55            base::ThreadTaskRunnerHandle::Get()));
56
57    fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
58        fake_drive_service.get(), drive_uploader.get(),
59        kSyncRootFolderTitle));
60
61    context_.reset(
62        new SyncEngineContext(
63            fake_drive_service.PassAs<drive::DriveServiceInterface>(),
64            drive_uploader.Pass(),
65            NULL,
66            base::ThreadTaskRunnerHandle::Get(),
67            base::ThreadTaskRunnerHandle::Get()));
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<LevelDBWrapper> 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(new LevelDBWrapper(make_scoped_ptr(db)));
89  }
90
91  void SetUpInitialData(LevelDBWrapper* 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    db->Put(kDatabaseVersionKey,
115            base::Int64ToString(kCurrentDatabaseVersion));
116    PutServiceMetadataToDB(service_metadata, db);
117    PutFileMetadataToDB(sync_root_metadata, db);
118    PutFileTrackerToDB(sync_root_tracker, db);
119    EXPECT_TRUE(db->Commit().ok());
120  }
121
122  void CreateMetadataDatabase(scoped_ptr<LevelDBWrapper> 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      LevelDBWrapper* 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    PutFileMetadataToDB(metadata, db);
162    PutFileTrackerToDB(tracker, db);
163    EXPECT_TRUE(db->Commit().ok());
164  }
165
166  void SetUpUnregisteredAppRoot(const std::string& app_id,
167                                LevelDBWrapper* db) {
168    FileDetails details;
169    details.set_title(app_id);
170    details.set_file_kind(FILE_KIND_FOLDER);
171    details.add_parent_folder_ids(sync_root_folder_id_);
172
173    FileMetadata metadata;
174    metadata.set_file_id(GenerateFileID());
175    *metadata.mutable_details() = details;
176
177    FileTracker tracker;
178    tracker.set_parent_tracker_id(kSyncRootTrackerID);
179    tracker.set_tracker_id(next_tracker_id_++);
180    tracker.set_file_id(metadata.file_id());
181    tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
182    *tracker.mutable_synced_details() = details;
183    tracker.set_active(false);
184
185    PutFileMetadataToDB(metadata, db);
186    PutFileTrackerToDB(tracker, db);
187    EXPECT_TRUE(db->Commit().ok());
188  }
189
190  size_t CountRegisteredAppRoot() {
191    std::vector<std::string> app_ids;
192    context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
193    return app_ids.size();
194  }
195
196  bool IsAppRegistered(const std::string& app_id) {
197    TrackerIDSet trackers;
198    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
199            kSyncRootTrackerID, app_id, &trackers))
200      return false;
201    return trackers.has_active();
202  }
203
204  size_t CountRemoteFileInSyncRoot() {
205    ScopedVector<google_apis::ResourceEntry> files;
206    EXPECT_EQ(google_apis::HTTP_SUCCESS,
207              fake_drive_service_helper_->ListFilesInFolder(
208                  sync_root_folder_id_, &files));
209    return files.size();
210  }
211
212  bool HasRemoteAppRoot(const std::string& app_id) {
213    TrackerIDSet files;
214    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
215            kSyncRootTrackerID, app_id, &files) ||
216        !files.has_active())
217      return false;
218
219    FileTracker app_root_tracker;
220    EXPECT_TRUE(context_->GetMetadataDatabase()->FindTrackerByTrackerID(
221        files.active_tracker(), &app_root_tracker));
222    std::string app_root_folder_id = app_root_tracker.file_id();
223    scoped_ptr<google_apis::FileResource> entry;
224    if (google_apis::HTTP_SUCCESS !=
225        fake_drive_service_helper_->GetFileResource(app_root_folder_id, &entry))
226      return false;
227
228    return !entry->labels().is_trashed();
229  }
230
231 private:
232  std::string GenerateFileID() {
233    return base::StringPrintf("file_id_%" PRId64, next_file_id_++);
234  }
235
236  scoped_ptr<leveldb::Env> in_memory_env_;
237
238  std::string sync_root_folder_id_;
239
240  int64 next_file_id_;
241  int64 next_tracker_id_;
242
243  content::TestBrowserThreadBundle browser_threads_;
244  base::ScopedTempDir database_dir_;
245
246  scoped_ptr<SyncEngineContext> context_;
247  scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
248
249  DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest);
250};
251
252TEST_F(RegisterAppTaskTest, AlreadyRegistered) {
253  scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
254  ASSERT_TRUE(db);
255  SetUpInitialData(db.get());
256
257  const std::string kAppID = "app_id";
258  SetUpRegisteredAppRoot(kAppID, db.get());
259
260  CreateMetadataDatabase(db.Pass());
261  EXPECT_EQ(SYNC_STATUS_OK, RunRegisterAppTask(kAppID));
262
263  EXPECT_EQ(1u, CountRegisteredAppRoot());
264  EXPECT_TRUE(IsAppRegistered(kAppID));
265}
266
267TEST_F(RegisterAppTaskTest, CreateAppFolder) {
268  scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
269  ASSERT_TRUE(db);
270  SetUpInitialData(db.get());
271
272  const std::string kAppID = "app_id";
273  CreateMetadataDatabase(db.Pass());
274  RunRegisterAppTask(kAppID);
275
276  EXPECT_EQ(1u, CountRegisteredAppRoot());
277  EXPECT_TRUE(IsAppRegistered(kAppID));
278
279  EXPECT_EQ(1u, CountRemoteFileInSyncRoot());
280  EXPECT_TRUE(HasRemoteAppRoot(kAppID));
281}
282
283TEST_F(RegisterAppTaskTest, RegisterExistingFolder) {
284  scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
285  ASSERT_TRUE(db);
286  SetUpInitialData(db.get());
287
288  const std::string kAppID = "app_id";
289  SetUpUnregisteredAppRoot(kAppID, db.get());
290
291  CreateMetadataDatabase(db.Pass());
292  RunRegisterAppTask(kAppID);
293
294  EXPECT_EQ(1u, CountRegisteredAppRoot());
295  EXPECT_TRUE(IsAppRegistered(kAppID));
296}
297
298TEST_F(RegisterAppTaskTest, RegisterExistingFolder_MultipleCandidate) {
299  scoped_ptr<LevelDBWrapper> db = OpenLevelDB();
300  ASSERT_TRUE(db);
301  SetUpInitialData(db.get());
302
303  const std::string kAppID = "app_id";
304  SetUpUnregisteredAppRoot(kAppID, db.get());
305  SetUpUnregisteredAppRoot(kAppID, db.get());
306
307  CreateMetadataDatabase(db.Pass());
308  RunRegisterAppTask(kAppID);
309
310  EXPECT_EQ(1u, CountRegisteredAppRoot());
311  EXPECT_TRUE(IsAppRegistered(kAppID));
312}
313
314}  // namespace drive_backend
315}  // namespace sync_file_system
316