register_app_task_unittest.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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    fake_drive_service_.reset(new drive::FakeDriveService);
50
51    drive_uploader_.reset(new drive::DriveUploader(
52        fake_drive_service_.get(), base::MessageLoopProxy::current()));
53
54    fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
55        fake_drive_service_.get(), drive_uploader_.get(),
56        kSyncRootFolderTitle));
57
58    context_.reset(
59        new SyncEngineContext(fake_drive_service_.get(),
60                              drive_uploader_.get(),
61                              base::MessageLoopProxy::current(),
62                              base::MessageLoopProxy::current(),
63                              base::MessageLoopProxy::current()));
64
65    ASSERT_EQ(google_apis::HTTP_CREATED,
66              fake_drive_service_helper_->AddOrphanedFolder(
67                  kSyncRootFolderTitle, &sync_root_folder_id_));
68  }
69
70  virtual void TearDown() OVERRIDE {
71    context_.reset();
72    fake_drive_service_.reset();
73    drive_uploader_.reset();
74    base::RunLoop().RunUntilIdle();
75  }
76
77 protected:
78  scoped_ptr<leveldb::DB> OpenLevelDB() {
79    leveldb::DB* db = NULL;
80    leveldb::Options options;
81    options.create_if_missing = true;
82    options.env = in_memory_env_.get();
83    leveldb::Status status =
84        leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
85    EXPECT_TRUE(status.ok());
86    return make_scoped_ptr<leveldb::DB>(db);
87  }
88
89  void SetUpInitialData(leveldb::DB* db) {
90    ServiceMetadata service_metadata;
91    service_metadata.set_largest_change_id(100);
92    service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
93    service_metadata.set_next_tracker_id(next_tracker_id_);
94
95    FileDetails sync_root_details;
96    sync_root_details.set_title(kSyncRootFolderTitle);
97    sync_root_details.set_file_kind(FILE_KIND_FOLDER);
98    sync_root_details.set_change_id(1);
99
100    FileMetadata sync_root_metadata;
101    sync_root_metadata.set_file_id(sync_root_folder_id_);
102    *sync_root_metadata.mutable_details() = sync_root_details;
103
104    FileTracker sync_root_tracker;
105    sync_root_tracker.set_tracker_id(service_metadata.sync_root_tracker_id());
106    sync_root_tracker.set_parent_tracker_id(0);
107    sync_root_tracker.set_file_id(sync_root_metadata.file_id());
108    sync_root_tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
109    *sync_root_tracker.mutable_synced_details() = sync_root_details;
110    sync_root_tracker.set_active(true);
111
112    leveldb::WriteBatch batch;
113    batch.Put(kDatabaseVersionKey,
114              base::Int64ToString(kCurrentDatabaseVersion));
115    PutServiceMetadataToBatch(service_metadata, &batch);
116    PutFileMetadataToBatch(sync_root_metadata, &batch);
117    PutFileTrackerToBatch(sync_root_tracker, &batch);
118    EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
119  }
120
121  void CreateMetadataDatabase(scoped_ptr<leveldb::DB> db) {
122    ASSERT_TRUE(db);
123    ASSERT_FALSE(context_->GetMetadataDatabase());
124    scoped_ptr<MetadataDatabase> metadata_db;
125    ASSERT_EQ(SYNC_STATUS_OK,
126              MetadataDatabase::CreateForTesting(
127                  db.Pass(), &metadata_db));
128    context_->SetMetadataDatabase(metadata_db.Pass());
129  }
130
131  SyncStatusCode RunRegisterAppTask(const std::string& app_id) {
132    RegisterAppTask task(context_.get(), app_id);
133    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
134    task.RunExclusive(CreateResultReceiver(&status));
135    base::RunLoop().RunUntilIdle();
136    return status;
137  }
138
139  void SetUpRegisteredAppRoot(
140      const std::string& app_id,
141      leveldb::DB* db) {
142    FileDetails details;
143    details.set_title(app_id);
144    details.set_file_kind(FILE_KIND_FOLDER);
145    details.add_parent_folder_ids(sync_root_folder_id_);
146
147    FileMetadata metadata;
148    metadata.set_file_id(GenerateFileID());
149    *metadata.mutable_details() = details;
150
151    FileTracker tracker;
152    tracker.set_parent_tracker_id(kSyncRootTrackerID);
153    tracker.set_tracker_id(next_tracker_id_++);
154    tracker.set_file_id(metadata.file_id());
155    tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
156    tracker.set_app_id(app_id);
157    *tracker.mutable_synced_details() = details;
158    tracker.set_active(true);
159
160    leveldb::WriteBatch batch;
161    PutFileMetadataToBatch(metadata, &batch);
162    PutFileTrackerToBatch(tracker, &batch);
163    EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
164  }
165
166  void SetUpUnregisteredAppRoot(const std::string& app_id,
167                                leveldb::DB* 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    leveldb::WriteBatch batch;
186    PutFileMetadataToBatch(metadata, &batch);
187    PutFileTrackerToBatch(tracker, &batch);
188    EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
189  }
190
191  size_t CountRegisteredAppRoot() {
192    std::vector<std::string> app_ids;
193    context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
194    return app_ids.size();
195  }
196
197  bool IsAppRegistered(const std::string& app_id) {
198    TrackerIDSet trackers;
199    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
200            kSyncRootTrackerID, app_id, &trackers))
201      return false;
202    return trackers.has_active();
203  }
204
205  size_t CountRemoteFileInSyncRoot() {
206    ScopedVector<google_apis::ResourceEntry> files;
207    EXPECT_EQ(google_apis::HTTP_SUCCESS,
208              fake_drive_service_helper_->ListFilesInFolder(
209                  sync_root_folder_id_, &files));
210    return files.size();
211  }
212
213  bool HasRemoteAppRoot(const std::string& app_id) {
214    TrackerIDSet files;
215    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
216            kSyncRootTrackerID, app_id, &files) ||
217        !files.has_active())
218      return false;
219
220    FileTracker app_root_tracker;
221    EXPECT_TRUE(context_->GetMetadataDatabase()->FindTrackerByTrackerID(
222        files.active_tracker(), &app_root_tracker));
223    std::string app_root_folder_id = app_root_tracker.file_id();
224    scoped_ptr<google_apis::ResourceEntry> entry;
225    if (google_apis::HTTP_SUCCESS !=
226        fake_drive_service_helper_->GetResourceEntry(
227            app_root_folder_id, &entry))
228      return false;
229
230    return !entry->deleted();
231  }
232
233 private:
234  std::string GenerateFileID() {
235    return base::StringPrintf("file_id_%" PRId64, next_file_id_++);
236  }
237
238  scoped_ptr<leveldb::Env> in_memory_env_;
239
240  std::string sync_root_folder_id_;
241
242  int64 next_file_id_;
243  int64 next_tracker_id_;
244
245  content::TestBrowserThreadBundle browser_threads_;
246  base::ScopedTempDir database_dir_;
247
248  scoped_ptr<SyncEngineContext> context_;
249  scoped_ptr<drive::FakeDriveService> fake_drive_service_;
250  scoped_ptr<drive::DriveUploaderInterface> drive_uploader_;
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