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.
5 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/drive/drive_api_util.h"
11 #include "chrome/browser/drive/drive_uploader.h"
12 #include "chrome/browser/drive/fake_drive_service.h"
13 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
14 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
15 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
16 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
17 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
18 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
19 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "google_apis/drive/drive_api_parser.h"
22 #include "google_apis/drive/gdata_wapi_parser.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
25 #include "third_party/leveldatabase/src/include/leveldb/env.h"
27 namespace sync_file_system {
28 namespace drive_backend {
32 const int64 kInitialLargestChangeID = 1234;
36 class SyncEngineInitializerTest : public testing::Test {
39 scoped_ptr<google_apis::FileResource> resource;
40 FileMetadata metadata;
44 SyncEngineInitializerTest() {}
45 virtual ~SyncEngineInitializerTest() {}
47 virtual void SetUp() OVERRIDE {
48 ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
49 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
51 scoped_ptr<drive::DriveServiceInterface>
52 fake_drive_service(new drive::FakeDriveService);
54 sync_context_.reset(new SyncEngineContext(
55 fake_drive_service.Pass(),
56 scoped_ptr<drive::DriveUploaderInterface>(),
57 base::MessageLoopProxy::current(),
58 base::MessageLoopProxy::current(),
59 base::MessageLoopProxy::current()));
61 sync_task_manager_.reset(new SyncTaskManager(
62 base::WeakPtr<SyncTaskManager::Client>(),
63 1 /* maximum_parallel_task */));
64 sync_task_manager_->Initialize(SYNC_STATUS_OK);
67 virtual void TearDown() OVERRIDE {
68 sync_task_manager_.reset();
69 metadata_database_.reset();
70 sync_context_.reset();
71 base::RunLoop().RunUntilIdle();
74 base::FilePath database_path() {
75 return database_dir_.path();
78 SyncStatusCode RunInitializer() {
79 SyncEngineInitializer* initializer =
80 new SyncEngineInitializer(
82 base::MessageLoopProxy::current(),
84 in_memory_env_.get());
85 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
87 sync_task_manager_->ScheduleSyncTask(
89 scoped_ptr<SyncTask>(initializer),
90 SyncTaskManager::PRIORITY_MED,
91 base::Bind(&SyncEngineInitializerTest::DidRunInitializer,
92 base::Unretained(this), initializer, &status));
94 base::RunLoop().RunUntilIdle();
98 void DidRunInitializer(SyncEngineInitializer* initializer,
99 SyncStatusCode* status_out,
100 SyncStatusCode status) {
101 *status_out = status;
102 metadata_database_ = initializer->PassMetadataDatabase();
105 SyncStatusCode PopulateDatabase(
106 const google_apis::FileResource& sync_root,
107 const google_apis::FileResource** app_roots,
108 size_t app_roots_count) {
109 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
110 scoped_ptr<MetadataDatabase> database;
111 MetadataDatabase::Create(
112 base::MessageLoopProxy::current(),
113 base::MessageLoopProxy::current(),
115 in_memory_env_.get(),
116 CreateResultReceiver(&status, &database));
117 base::RunLoop().RunUntilIdle();
118 if (status != SYNC_STATUS_OK)
121 // |app_root_list| must not own the resources here. Be sure to call
123 ScopedVector<google_apis::FileResource> app_root_list;
124 for (size_t i = 0; i < app_roots_count; ++i) {
125 app_root_list.push_back(
126 const_cast<google_apis::FileResource*>(app_roots[i]));
129 status = SYNC_STATUS_UNKNOWN;
130 database->PopulateInitialData(kInitialLargestChangeID,
133 CreateResultReceiver(&status));
134 base::RunLoop().RunUntilIdle();
136 app_root_list.weak_clear();
138 return SYNC_STATUS_OK;
141 scoped_ptr<google_apis::FileResource> CreateRemoteFolder(
142 const std::string& parent_folder_id,
143 const std::string& title) {
144 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
145 scoped_ptr<google_apis::ResourceEntry> entry;
146 sync_context_->GetDriveService()->AddNewDirectory(
147 parent_folder_id, title,
148 drive::DriveServiceInterface::AddNewDirectoryOptions(),
149 CreateResultReceiver(&error, &entry));
150 base::RunLoop().RunUntilIdle();
152 EXPECT_EQ(google_apis::HTTP_CREATED, error);
154 scoped_ptr<google_apis::FileResource>();
155 return drive::util::ConvertResourceEntryToFileResource(*entry);
158 scoped_ptr<google_apis::FileResource> CreateRemoteSyncRoot() {
159 scoped_ptr<google_apis::FileResource> sync_root(
160 CreateRemoteFolder(std::string(), kSyncRootFolderTitle));
162 for (size_t i = 0; i < sync_root->parents().size(); ++i) {
163 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
164 sync_context_->GetDriveService()->RemoveResourceFromDirectory(
165 sync_root->parents()[i].file_id(),
166 sync_root->file_id(),
167 CreateResultReceiver(&error));
168 base::RunLoop().RunUntilIdle();
169 EXPECT_EQ(google_apis::HTTP_NO_CONTENT, error);
172 return sync_root.Pass();
175 std::string GetSyncRootFolderID() {
176 int64 sync_root_tracker_id = metadata_database_->GetSyncRootTrackerID();
177 FileTracker sync_root_tracker;
178 EXPECT_TRUE(metadata_database_->FindTrackerByTrackerID(
179 sync_root_tracker_id, &sync_root_tracker));
180 return sync_root_tracker.file_id();
183 size_t CountTrackersForFile(const std::string& file_id) {
184 TrackerIDSet trackers;
185 metadata_database_->FindTrackersByFileID(file_id, &trackers);
186 return trackers.size();
189 bool HasActiveTracker(const std::string& file_id) {
190 TrackerIDSet trackers;
191 return metadata_database_->FindTrackersByFileID(file_id, &trackers) &&
192 trackers.has_active();
195 bool HasNoParent(const std::string& file_id) {
196 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
197 scoped_ptr<google_apis::ResourceEntry> entry;
198 sync_context_->GetDriveService()->GetResourceEntry(
200 CreateResultReceiver(&error, &entry));
201 base::RunLoop().RunUntilIdle();
202 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
203 return !entry->GetLinkByType(google_apis::Link::LINK_PARENT);
206 size_t CountFileMetadata() {
207 return metadata_database_->CountFileMetadata();
210 size_t CountFileTracker() {
211 return metadata_database_->CountFileTracker();
214 google_apis::GDataErrorCode AddParentFolder(
215 const std::string& new_parent_folder_id,
216 const std::string& file_id) {
217 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
218 sync_context_->GetDriveService()->AddResourceToDirectory(
219 new_parent_folder_id, file_id,
220 CreateResultReceiver(&error));
221 base::RunLoop().RunUntilIdle();
226 content::TestBrowserThreadBundle browser_threads_;
227 base::ScopedTempDir database_dir_;
228 scoped_ptr<leveldb::Env> in_memory_env_;
230 scoped_ptr<MetadataDatabase> metadata_database_;
231 scoped_ptr<SyncTaskManager> sync_task_manager_;
232 scoped_ptr<SyncEngineContext> sync_context_;
234 DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest);
237 TEST_F(SyncEngineInitializerTest, EmptyDatabase_NoRemoteSyncRoot) {
238 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
240 std::string sync_root_folder_id = GetSyncRootFolderID();
241 EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id));
243 EXPECT_TRUE(HasActiveTracker(sync_root_folder_id));
245 EXPECT_EQ(1u, CountFileMetadata());
246 EXPECT_EQ(1u, CountFileTracker());
249 TEST_F(SyncEngineInitializerTest, EmptyDatabase_RemoteSyncRootExists) {
250 scoped_ptr<google_apis::FileResource> sync_root(
251 CreateRemoteSyncRoot());
252 scoped_ptr<google_apis::FileResource> app_root_1(
253 CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
254 scoped_ptr<google_apis::FileResource> app_root_2(
255 CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
257 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
259 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
260 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
261 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
263 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
264 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
265 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
267 EXPECT_EQ(3u, CountFileMetadata());
268 EXPECT_EQ(3u, CountFileTracker());
271 TEST_F(SyncEngineInitializerTest, DatabaseAlreadyInitialized) {
272 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteSyncRoot());
273 scoped_ptr<google_apis::FileResource> app_root_1(
274 CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
275 scoped_ptr<google_apis::FileResource> app_root_2(
276 CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
278 const google_apis::FileResource* app_roots[] = {
279 app_root_1.get(), app_root_2.get()
281 EXPECT_EQ(SYNC_STATUS_OK,
282 PopulateDatabase(*sync_root, app_roots, arraysize(app_roots)));
284 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
286 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
287 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
288 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
290 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
291 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
292 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
294 EXPECT_EQ(3u, CountFileMetadata());
295 EXPECT_EQ(3u, CountFileTracker());
298 TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiCandidate) {
299 scoped_ptr<google_apis::FileResource> sync_root_1(CreateRemoteSyncRoot());
300 scoped_ptr<google_apis::FileResource> sync_root_2(CreateRemoteSyncRoot());
302 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
304 EXPECT_EQ(1u, CountTrackersForFile(sync_root_1->file_id()));
305 EXPECT_EQ(0u, CountTrackersForFile(sync_root_2->file_id()));
307 EXPECT_TRUE(HasActiveTracker(sync_root_1->file_id()));
308 EXPECT_FALSE(HasActiveTracker(sync_root_2->file_id()));
310 EXPECT_EQ(1u, CountFileMetadata());
311 EXPECT_EQ(1u, CountFileTracker());
314 TEST_F(SyncEngineInitializerTest, EmptyDatabase_UndetachedRemoteSyncRoot) {
315 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
316 std::string(), kSyncRootFolderTitle));
317 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
319 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
320 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
322 EXPECT_TRUE(HasNoParent(sync_root->file_id()));
324 EXPECT_EQ(1u, CountFileMetadata());
325 EXPECT_EQ(1u, CountFileTracker());
328 TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiparentSyncRoot) {
329 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
330 std::string(), "folder"));
331 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
332 std::string(), kSyncRootFolderTitle));
333 AddParentFolder(sync_root->file_id(), folder->file_id());
335 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
337 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
338 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
340 EXPECT_TRUE(HasNoParent(sync_root->file_id()));
342 EXPECT_EQ(1u, CountFileMetadata());
343 EXPECT_EQ(1u, CountFileTracker());
346 TEST_F(SyncEngineInitializerTest, EmptyDatabase_FakeRemoteSyncRoot) {
347 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
348 std::string(), "folder"));
349 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
350 folder->file_id(), kSyncRootFolderTitle));
352 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
354 EXPECT_EQ(0u, CountTrackersForFile(sync_root->file_id()));
355 EXPECT_FALSE(HasNoParent(sync_root->file_id()));
357 EXPECT_EQ(1u, CountFileMetadata());
358 EXPECT_EQ(1u, CountFileTracker());
361 } // namespace drive_backend
362 } // namespace sync_file_system