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 "base/thread_task_runner_handle.h"
11 #include "chrome/browser/drive/drive_api_util.h"
12 #include "chrome/browser/drive/drive_uploader.h"
13 #include "chrome/browser/drive/fake_drive_service.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_test_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/sync_task_manager.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 "google_apis/drive/drive_api_parser.h"
23 #include "google_apis/drive/gdata_wapi_parser.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
26 #include "third_party/leveldatabase/src/include/leveldb/env.h"
28 namespace sync_file_system {
29 namespace drive_backend {
33 const int64 kInitialLargestChangeID = 1234;
37 class SyncEngineInitializerTest : public testing::Test {
40 scoped_ptr<google_apis::FileResource> resource;
41 FileMetadata metadata;
45 SyncEngineInitializerTest() {}
46 virtual ~SyncEngineInitializerTest() {}
48 virtual void SetUp() OVERRIDE {
49 ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
50 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
52 scoped_ptr<drive::DriveServiceInterface>
53 fake_drive_service(new drive::FakeDriveService);
55 sync_context_.reset(new SyncEngineContext(
56 fake_drive_service.Pass(),
57 scoped_ptr<drive::DriveUploaderInterface>(),
59 base::ThreadTaskRunnerHandle::Get(),
60 base::ThreadTaskRunnerHandle::Get()));
62 sync_task_manager_.reset(new SyncTaskManager(
63 base::WeakPtr<SyncTaskManager::Client>(),
64 1 /* maximum_parallel_task */,
65 base::ThreadTaskRunnerHandle::Get()));
66 sync_task_manager_->Initialize(SYNC_STATUS_OK);
69 virtual void TearDown() OVERRIDE {
70 sync_task_manager_.reset();
71 metadata_database_.reset();
72 sync_context_.reset();
73 base::RunLoop().RunUntilIdle();
76 base::FilePath database_path() {
77 return database_dir_.path();
80 SyncStatusCode RunInitializer() {
81 SyncEngineInitializer* initializer =
82 new SyncEngineInitializer(sync_context_.get(),
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 = MetadataDatabase::Create(
111 database_path(), in_memory_env_.get(), &status);
112 if (status != SYNC_STATUS_OK)
115 // |app_root_list| must not own the resources here. Be sure to call
117 ScopedVector<google_apis::FileResource> app_root_list;
118 for (size_t i = 0; i < app_roots_count; ++i) {
119 app_root_list.push_back(
120 const_cast<google_apis::FileResource*>(app_roots[i]));
123 status = database->PopulateInitialData(
124 kInitialLargestChangeID, sync_root, app_root_list);
126 app_root_list.weak_clear();
130 scoped_ptr<google_apis::FileResource> CreateRemoteFolder(
131 const std::string& parent_folder_id,
132 const std::string& title) {
133 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
134 scoped_ptr<google_apis::FileResource> entry;
135 sync_context_->GetDriveService()->AddNewDirectory(
136 parent_folder_id, title,
137 drive::DriveServiceInterface::AddNewDirectoryOptions(),
138 CreateResultReceiver(&error, &entry));
139 base::RunLoop().RunUntilIdle();
141 EXPECT_EQ(google_apis::HTTP_CREATED, error);
145 scoped_ptr<google_apis::FileResource> CreateRemoteSyncRoot() {
146 scoped_ptr<google_apis::FileResource> sync_root(
147 CreateRemoteFolder(std::string(), kSyncRootFolderTitle));
149 for (size_t i = 0; i < sync_root->parents().size(); ++i) {
150 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
151 sync_context_->GetDriveService()->RemoveResourceFromDirectory(
152 sync_root->parents()[i].file_id(),
153 sync_root->file_id(),
154 CreateResultReceiver(&error));
155 base::RunLoop().RunUntilIdle();
156 EXPECT_EQ(google_apis::HTTP_NO_CONTENT, error);
159 return sync_root.Pass();
162 std::string GetSyncRootFolderID() {
163 int64 sync_root_tracker_id = metadata_database_->GetSyncRootTrackerID();
164 FileTracker sync_root_tracker;
165 EXPECT_TRUE(metadata_database_->FindTrackerByTrackerID(
166 sync_root_tracker_id, &sync_root_tracker));
167 return sync_root_tracker.file_id();
170 size_t CountTrackersForFile(const std::string& file_id) {
171 TrackerIDSet trackers;
172 metadata_database_->FindTrackersByFileID(file_id, &trackers);
173 return trackers.size();
176 bool HasActiveTracker(const std::string& file_id) {
177 TrackerIDSet trackers;
178 return metadata_database_->FindTrackersByFileID(file_id, &trackers) &&
179 trackers.has_active();
182 bool HasNoParent(const std::string& file_id) {
183 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
184 scoped_ptr<google_apis::FileResource> entry;
185 sync_context_->GetDriveService()->GetFileResource(
187 CreateResultReceiver(&error, &entry));
188 base::RunLoop().RunUntilIdle();
189 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
190 return entry->parents().empty();
193 size_t CountFileMetadata() {
194 return metadata_database_->CountFileMetadata();
197 size_t CountFileTracker() {
198 return metadata_database_->CountFileTracker();
201 google_apis::GDataErrorCode AddParentFolder(
202 const std::string& new_parent_folder_id,
203 const std::string& file_id) {
204 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
205 sync_context_->GetDriveService()->AddResourceToDirectory(
206 new_parent_folder_id, file_id,
207 CreateResultReceiver(&error));
208 base::RunLoop().RunUntilIdle();
213 content::TestBrowserThreadBundle browser_threads_;
214 base::ScopedTempDir database_dir_;
215 scoped_ptr<leveldb::Env> in_memory_env_;
217 scoped_ptr<MetadataDatabase> metadata_database_;
218 scoped_ptr<SyncTaskManager> sync_task_manager_;
219 scoped_ptr<SyncEngineContext> sync_context_;
221 DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest);
224 TEST_F(SyncEngineInitializerTest, EmptyDatabase_NoRemoteSyncRoot) {
225 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
227 std::string sync_root_folder_id = GetSyncRootFolderID();
228 EXPECT_EQ(1u, CountTrackersForFile(sync_root_folder_id));
230 EXPECT_TRUE(HasActiveTracker(sync_root_folder_id));
232 EXPECT_EQ(1u, CountFileMetadata());
233 EXPECT_EQ(1u, CountFileTracker());
236 TEST_F(SyncEngineInitializerTest, EmptyDatabase_RemoteSyncRootExists) {
237 scoped_ptr<google_apis::FileResource> sync_root(
238 CreateRemoteSyncRoot());
239 scoped_ptr<google_apis::FileResource> app_root_1(
240 CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
241 scoped_ptr<google_apis::FileResource> app_root_2(
242 CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
244 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
246 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
247 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
248 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
250 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
251 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
252 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
254 EXPECT_EQ(3u, CountFileMetadata());
255 EXPECT_EQ(3u, CountFileTracker());
258 TEST_F(SyncEngineInitializerTest, DatabaseAlreadyInitialized) {
259 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteSyncRoot());
260 scoped_ptr<google_apis::FileResource> app_root_1(
261 CreateRemoteFolder(sync_root->file_id(), "app-root 1"));
262 scoped_ptr<google_apis::FileResource> app_root_2(
263 CreateRemoteFolder(sync_root->file_id(), "app-root 2"));
265 const google_apis::FileResource* app_roots[] = {
266 app_root_1.get(), app_root_2.get()
268 EXPECT_EQ(SYNC_STATUS_OK,
269 PopulateDatabase(*sync_root, app_roots, arraysize(app_roots)));
271 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
273 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
274 EXPECT_EQ(1u, CountTrackersForFile(app_root_1->file_id()));
275 EXPECT_EQ(1u, CountTrackersForFile(app_root_2->file_id()));
277 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
278 EXPECT_FALSE(HasActiveTracker(app_root_1->file_id()));
279 EXPECT_FALSE(HasActiveTracker(app_root_2->file_id()));
281 EXPECT_EQ(3u, CountFileMetadata());
282 EXPECT_EQ(3u, CountFileTracker());
285 TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiCandidate) {
286 scoped_ptr<google_apis::FileResource> sync_root_1(CreateRemoteSyncRoot());
287 scoped_ptr<google_apis::FileResource> sync_root_2(CreateRemoteSyncRoot());
289 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
291 EXPECT_EQ(1u, CountTrackersForFile(sync_root_1->file_id()));
292 EXPECT_EQ(0u, CountTrackersForFile(sync_root_2->file_id()));
294 EXPECT_TRUE(HasActiveTracker(sync_root_1->file_id()));
295 EXPECT_FALSE(HasActiveTracker(sync_root_2->file_id()));
297 EXPECT_EQ(1u, CountFileMetadata());
298 EXPECT_EQ(1u, CountFileTracker());
301 TEST_F(SyncEngineInitializerTest, EmptyDatabase_UndetachedRemoteSyncRoot) {
302 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
303 std::string(), kSyncRootFolderTitle));
304 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
306 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
307 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
309 EXPECT_TRUE(HasNoParent(sync_root->file_id()));
311 EXPECT_EQ(1u, CountFileMetadata());
312 EXPECT_EQ(1u, CountFileTracker());
315 TEST_F(SyncEngineInitializerTest, EmptyDatabase_MultiparentSyncRoot) {
316 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
317 std::string(), "folder"));
318 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
319 std::string(), kSyncRootFolderTitle));
320 AddParentFolder(sync_root->file_id(), folder->file_id());
322 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
324 EXPECT_EQ(1u, CountTrackersForFile(sync_root->file_id()));
325 EXPECT_TRUE(HasActiveTracker(sync_root->file_id()));
327 EXPECT_TRUE(HasNoParent(sync_root->file_id()));
329 EXPECT_EQ(1u, CountFileMetadata());
330 EXPECT_EQ(1u, CountFileTracker());
333 TEST_F(SyncEngineInitializerTest, EmptyDatabase_FakeRemoteSyncRoot) {
334 scoped_ptr<google_apis::FileResource> folder(CreateRemoteFolder(
335 std::string(), "folder"));
336 scoped_ptr<google_apis::FileResource> sync_root(CreateRemoteFolder(
337 folder->file_id(), kSyncRootFolderTitle));
339 EXPECT_EQ(SYNC_STATUS_OK, RunInitializer());
341 EXPECT_EQ(0u, CountTrackersForFile(sync_root->file_id()));
342 EXPECT_FALSE(HasNoParent(sync_root->file_id()));
344 EXPECT_EQ(1u, CountFileMetadata());
345 EXPECT_EQ(1u, CountFileTracker());
348 } // namespace drive_backend
349 } // namespace sync_file_system