- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / register_app_task_unittest.cc
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 "base/files/scoped_temp_dir.h"
8 #include "base/format_macros.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/drive/fake_drive_service.h"
13 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
15 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
16 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
17 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
18 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
19 #include "chrome/browser/sync_file_system/drive_backend_v1/fake_drive_service_helper.h"
20 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/leveldatabase/src/include/leveldb/db.h"
24 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
25
26 namespace sync_file_system {
27 namespace drive_backend {
28
29 namespace {
30 const int64 kSyncRootTrackerID = 100;
31 }  // namespace
32
33 class RegisterAppTaskTest : public testing::Test,
34                             public SyncEngineContext {
35  public:
36   RegisterAppTaskTest()
37       : next_file_id_(1000),
38         next_tracker_id_(10000) {}
39   virtual ~RegisterAppTaskTest() {}
40
41   virtual void SetUp() OVERRIDE {
42     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
43
44     fake_drive_service_.reset(new drive::FakeDriveService);
45     ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
46         "sync_file_system/account_metadata.json"));
47     ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
48         "gdata/empty_feed.json"));
49
50     drive_uploader_.reset(new drive::DriveUploader(
51         fake_drive_service_.get(), base::MessageLoopProxy::current()));
52
53     fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
54         fake_drive_service_.get(), drive_uploader_.get()));
55
56     ASSERT_EQ(google_apis::HTTP_CREATED,
57               fake_drive_service_helper_->AddOrphanedFolder(
58                   kSyncRootFolderTitle, &sync_root_folder_id_));
59   }
60
61   virtual void TearDown() OVERRIDE {
62     metadata_database_.reset();
63     base::RunLoop().RunUntilIdle();
64   }
65
66   virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
67     return fake_drive_service_.get();
68   }
69
70   virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
71     return metadata_database_.get();
72   }
73
74  protected:
75   scoped_ptr<leveldb::DB> OpenLevelDB() {
76     leveldb::DB* db = NULL;
77     leveldb::Options options;
78     options.create_if_missing = true;
79     leveldb::Status status =
80         leveldb::DB::Open(options, database_dir_.path().AsUTF8Unsafe(), &db);
81     EXPECT_TRUE(status.ok());
82     return make_scoped_ptr<leveldb::DB>(db);
83   }
84
85   void SetUpInitialData(leveldb::DB* db) {
86     ServiceMetadata service_metadata;
87     service_metadata.set_largest_change_id(100);
88     service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
89     service_metadata.set_next_tracker_id(next_tracker_id_);
90
91     FileDetails sync_root_details;
92     sync_root_details.set_title(kSyncRootFolderTitle);
93     sync_root_details.set_file_kind(FILE_KIND_FOLDER);
94     sync_root_details.set_change_id(1);
95
96     FileMetadata sync_root_metadata;
97     sync_root_metadata.set_file_id(sync_root_folder_id_);
98     *sync_root_metadata.mutable_details() = sync_root_details;
99
100     FileTracker sync_root_tracker;
101     sync_root_tracker.set_tracker_id(service_metadata.sync_root_tracker_id());
102     sync_root_tracker.set_parent_tracker_id(0);
103     sync_root_tracker.set_file_id(sync_root_metadata.file_id());
104     sync_root_tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
105     *sync_root_tracker.mutable_synced_details() = sync_root_details;
106     sync_root_tracker.set_active(true);
107
108     leveldb::WriteBatch batch;
109     batch.Put(kDatabaseVersionKey,
110               base::Int64ToString(kCurrentDatabaseVersion));
111     PutServiceMetadataToBatch(service_metadata, &batch);
112     PutFileToBatch(sync_root_metadata, &batch);
113     PutTrackerToBatch(sync_root_tracker, &batch);
114     EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
115   }
116
117   void CreateMetadataDatabase(scoped_ptr<leveldb::DB> db) {
118     ASSERT_TRUE(db);
119     ASSERT_FALSE(metadata_database_);
120     ASSERT_EQ(SYNC_STATUS_OK,
121               MetadataDatabase::CreateForTesting(
122                   db.Pass(), &metadata_database_));
123   }
124
125   SyncStatusCode RunRegisterAppTask(const std::string& app_id) {
126     RegisterAppTask task(this, app_id);
127     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
128     task.Run(CreateResultReceiver(&status));
129     base::RunLoop().RunUntilIdle();
130     return status;
131   }
132
133   void SetUpRegisteredAppRoot(
134       const std::string& app_id,
135       leveldb::DB* db) {
136     FileDetails details;
137     details.set_title(app_id);
138     details.set_file_kind(FILE_KIND_FOLDER);
139     details.add_parent_folder_ids(sync_root_folder_id_);
140
141     FileMetadata metadata;
142     metadata.set_file_id(GenerateFileID());
143     *metadata.mutable_details() = details;
144
145     FileTracker tracker;
146     tracker.set_parent_tracker_id(kSyncRootTrackerID);
147     tracker.set_tracker_id(next_tracker_id_++);
148     tracker.set_file_id(metadata.file_id());
149     tracker.set_tracker_kind(TRACKER_KIND_APP_ROOT);
150     tracker.set_app_id(app_id);
151     *tracker.mutable_synced_details() = details;
152     tracker.set_active(true);
153
154     leveldb::WriteBatch batch;
155     PutFileToBatch(metadata, &batch);
156     PutTrackerToBatch(tracker, &batch);
157     EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
158   }
159
160   void SetUpUnregisteredAppRoot(const std::string& app_id,
161                                 leveldb::DB* db) {
162     FileDetails details;
163     details.set_title(app_id);
164     details.set_file_kind(FILE_KIND_FOLDER);
165     details.add_parent_folder_ids(sync_root_folder_id_);
166
167     FileMetadata metadata;
168     metadata.set_file_id(GenerateFileID());
169     *metadata.mutable_details() = details;
170
171     FileTracker tracker;
172     tracker.set_parent_tracker_id(kSyncRootTrackerID);
173     tracker.set_tracker_id(next_tracker_id_++);
174     tracker.set_file_id(metadata.file_id());
175     tracker.set_tracker_kind(TRACKER_KIND_REGULAR);
176     *tracker.mutable_synced_details() = details;
177     tracker.set_active(false);
178
179     leveldb::WriteBatch batch;
180     PutFileToBatch(metadata, &batch);
181     PutTrackerToBatch(tracker, &batch);
182     EXPECT_TRUE(db->Write(leveldb::WriteOptions(), &batch).ok());
183   }
184
185   size_t CountRegisteredAppRoot() {
186     // TODO(tzik): Add function to MetadataDatabase to list trackers by parent.
187     typedef MetadataDatabase::TrackersByTitle TrackersByTitle;
188     const TrackersByTitle& trackers_by_title =
189         metadata_database_->trackers_by_parent_and_title_[kSyncRootTrackerID];
190
191     size_t count = 0;
192     for (TrackersByTitle::const_iterator itr = trackers_by_title.begin();
193          itr != trackers_by_title.end(); ++itr) {
194       if (itr->second.has_active())
195         ++count;
196     }
197
198     return count;
199   }
200
201   bool IsAppRegistered(const std::string& app_id) {
202     TrackerSet trackers;
203     if (!metadata_database_->FindTrackersByParentAndTitle(
204             kSyncRootTrackerID, app_id, &trackers))
205       return false;
206     return trackers.has_active();
207   }
208
209   size_t CountRemoteFileInSyncRoot() {
210     ScopedVector<google_apis::ResourceEntry> files;
211     EXPECT_EQ(google_apis::HTTP_SUCCESS,
212               fake_drive_service_helper_->ListFilesInFolder(
213                   sync_root_folder_id_, &files));
214     return files.size();
215   }
216
217   bool HasRemoteAppRoot(const std::string& app_id) {
218     TrackerSet files;
219     if (!metadata_database_->FindTrackersByParentAndTitle(
220             kSyncRootTrackerID, app_id, &files) ||
221         !files.has_active())
222       return false;
223
224     std::string app_root_folder_id = files.active_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   std::string sync_root_folder_id_;
240
241   int64 next_file_id_;
242   int64 next_tracker_id_;
243
244   content::TestBrowserThreadBundle browser_threads_;
245   base::ScopedTempDir database_dir_;
246
247   scoped_ptr<drive::FakeDriveService> fake_drive_service_;
248   scoped_ptr<drive::DriveUploader> drive_uploader_;
249   scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
250
251   scoped_ptr<MetadataDatabase> metadata_database_;
252
253   DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest);
254 };
255
256 TEST_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
271 TEST_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
287 TEST_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
302 TEST_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