Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / drive_backend / drive_backend_sync_unittest.cc
blob5d55c2bcbfd08bb1f45f5bc964ddc61373da285d
1 // Copyright 2014 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 <algorithm>
7 #include "base/file_util.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/drive/drive_uploader.h"
11 #include "chrome/browser/drive/fake_drive_service.h"
12 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
13 #include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
14 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
15 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
16 #include "chrome/browser/sync_file_system/drive_backend/sync_engine.h"
17 #include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
18 #include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
19 #include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
20 #include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
21 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
22 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "extensions/common/extension.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "webkit/browser/fileapi/file_system_context.h"
30 #define FPL(a) FILE_PATH_LITERAL(a)
32 namespace sync_file_system {
33 namespace drive_backend {
35 class DriveBackendSyncTest : public testing::Test {
36 public:
37 DriveBackendSyncTest()
38 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
39 virtual ~DriveBackendSyncTest() {}
41 virtual void SetUp() OVERRIDE {
42 ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
44 io_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
45 content::BrowserThread::IO);
46 file_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
47 content::BrowserThread::FILE);
49 RegisterSyncableFileSystem();
50 local_sync_service_.reset(new LocalFileSyncService(&profile_));
52 scoped_ptr<drive::FakeDriveService> drive_service(
53 new drive::FakeDriveService());
54 drive_service->Initialize("test@example.com");
55 ASSERT_TRUE(drive_service->LoadAccountMetadataForWapi(
56 "sync_file_system/account_metadata.json"));
57 ASSERT_TRUE(drive_service->LoadResourceListForWapi(
58 "gdata/root_feed.json"));
60 scoped_ptr<drive::DriveUploaderInterface> uploader(
61 new drive::DriveUploader(drive_service.get(),
62 file_task_runner_.get()));
64 remote_sync_service_.reset(new SyncEngine(
65 base_dir_.path(),
66 file_task_runner_.get(),
67 drive_service.PassAs<drive::DriveServiceInterface>(),
68 uploader.Pass(),
69 NULL, NULL, NULL));
70 remote_sync_service_->Initialize();
72 fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
73 fake_drive_service(), drive_uploader(),
74 kSyncRootFolderTitle));
76 local_sync_service_->SetLocalChangeProcessor(remote_sync_service_.get());
77 remote_sync_service_->SetRemoteChangeProcessor(local_sync_service_.get());
80 virtual void TearDown() OVERRIDE {
81 typedef std::map<std::string, CannedSyncableFileSystem*>::iterator iterator;
82 for (iterator itr = file_systems_.begin();
83 itr != file_systems_.end(); ++itr) {
84 itr->second->TearDown();
85 delete itr->second;
87 file_systems_.clear();
89 fake_drive_service_helper_.reset();
90 remote_sync_service_.reset();
92 base::RunLoop().RunUntilIdle();
93 RevokeSyncableFileSystem();
96 protected:
97 fileapi::FileSystemURL CreateURL(const std::string& app_id,
98 const base::FilePath::StringType& path) {
99 return CreateURL(app_id, base::FilePath(path));
102 fileapi::FileSystemURL CreateURL(const std::string& app_id,
103 const base::FilePath& path) {
104 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
105 return CreateSyncableFileSystemURL(origin, path);
108 bool GetAppRootFolderID(const std::string& app_id,
109 std::string* folder_id) {
110 FileTracker tracker;
111 if (!metadata_database()->FindAppRootTracker(app_id, &tracker))
112 return false;
113 *folder_id = tracker.file_id();
114 return true;
117 bool GetFileIDByPath(const std::string& app_id,
118 const base::FilePath& path,
119 std::string* file_id) {
120 FileTracker tracker;
121 base::FilePath result_path;
122 if (!metadata_database()->FindNearestActiveAncestor(
123 app_id, path, &tracker, &result_path) ||
124 path != result_path)
125 return false;
126 *file_id = tracker.file_id();
127 return true;
130 SyncStatusCode RegisterApp(const std::string& app_id) {
131 GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
132 if (!ContainsKey(file_systems_, app_id)) {
133 CannedSyncableFileSystem* file_system = new CannedSyncableFileSystem(
134 origin, io_task_runner_.get(), file_task_runner_.get());
135 file_system->SetUp();
137 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
138 local_sync_service_->MaybeInitializeFileSystemContext(
139 origin, file_system->file_system_context(),
140 CreateResultReceiver(&status));
141 base::RunLoop().RunUntilIdle();
142 EXPECT_EQ(SYNC_STATUS_OK, status);
144 file_system->backend()->sync_context()->
145 set_mock_notify_changes_duration_in_sec(0);
147 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system->OpenFileSystem());
148 file_systems_[app_id] = file_system;
151 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
152 remote_sync_service_->RegisterOrigin(origin, CreateResultReceiver(&status));
153 base::RunLoop().RunUntilIdle();
154 return status;
157 void AddLocalFolder(const std::string& app_id,
158 const base::FilePath::StringType& path) {
159 ASSERT_TRUE(ContainsKey(file_systems_, app_id));
160 EXPECT_EQ(base::PLATFORM_FILE_OK,
161 file_systems_[app_id]->CreateDirectory(
162 CreateURL(app_id, path)));
165 void AddOrUpdateLocalFile(const std::string& app_id,
166 const base::FilePath::StringType& path,
167 const std::string& content) {
168 fileapi::FileSystemURL url(CreateURL(app_id, path));
169 ASSERT_TRUE(ContainsKey(file_systems_, app_id));
170 EXPECT_EQ(base::PLATFORM_FILE_OK, file_systems_[app_id]->CreateFile(url));
171 int64 bytes_written = file_systems_[app_id]->WriteString(url, content);
172 EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
173 base::RunLoop().RunUntilIdle();
176 void UpdateLocalFile(const std::string& app_id,
177 const base::FilePath::StringType& path,
178 const std::string& content) {
179 ASSERT_TRUE(ContainsKey(file_systems_, app_id));
180 int64 bytes_written = file_systems_[app_id]->WriteString(
181 CreateURL(app_id, path), content);
182 EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
183 base::RunLoop().RunUntilIdle();
186 void RemoveLocal(const std::string& app_id,
187 const base::FilePath::StringType& path) {
188 ASSERT_TRUE(ContainsKey(file_systems_, app_id));
189 EXPECT_EQ(base::PLATFORM_FILE_OK,
190 file_systems_[app_id]->Remove(
191 CreateURL(app_id, path),
192 true /* recursive */));
193 base::RunLoop().RunUntilIdle();
196 SyncStatusCode ProcessLocalChange() {
197 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
198 fileapi::FileSystemURL url;
199 local_sync_service_->ProcessLocalChange(
200 CreateResultReceiver(&status, &url));
201 base::RunLoop().RunUntilIdle();
202 return status;
205 SyncStatusCode ProcessRemoteChange() {
206 SyncStatusCode status = SYNC_STATUS_UNKNOWN;
207 fileapi::FileSystemURL url;
208 remote_sync_service_->ProcessRemoteChange(
209 CreateResultReceiver(&status, &url));
210 base::RunLoop().RunUntilIdle();
211 return status;
214 SyncStatusCode ProcessChangesUntilDone() {
215 SyncStatusCode local_sync_status;
216 SyncStatusCode remote_sync_status;
217 do {
218 remote_sync_service_->OnNotificationReceived();
219 base::RunLoop().RunUntilIdle();
221 local_sync_status = ProcessLocalChange();
222 if (local_sync_status != SYNC_STATUS_OK &&
223 local_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
224 return local_sync_status;
226 remote_sync_status = ProcessRemoteChange();
227 if (remote_sync_status != SYNC_STATUS_OK &&
228 remote_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
229 return remote_sync_status;
230 } while (local_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC ||
231 remote_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC);
232 return SYNC_STATUS_OK;
235 // Verifies local and remote files/folders are consistent.
236 // This function checks:
237 // - Each registered origin has corresponding remote folder.
238 // - Each local file/folder has corresponding remote one.
239 // - Each remote file/folder has corresponding local one.
240 // TODO(tzik): Handle conflict case. i.e. allow remote file has different
241 // file content if the corresponding local file conflicts to it.
242 void VerifyConsistency() {
243 std::string sync_root_folder_id;
244 google_apis::GDataErrorCode error =
245 fake_drive_service_helper_->GetSyncRootFolderID(&sync_root_folder_id);
246 if (sync_root_folder_id.empty()) {
247 EXPECT_EQ(google_apis::HTTP_NOT_FOUND, error);
248 EXPECT_TRUE(file_systems_.empty());
249 return;
251 EXPECT_EQ(google_apis::HTTP_SUCCESS, error);
253 ScopedVector<google_apis::ResourceEntry> remote_entries;
254 EXPECT_EQ(google_apis::HTTP_SUCCESS,
255 fake_drive_service_helper_->ListFilesInFolder(
256 sync_root_folder_id, &remote_entries));
257 std::map<std::string, const google_apis::ResourceEntry*> app_root_by_title;
258 for (ScopedVector<google_apis::ResourceEntry>::iterator itr =
259 remote_entries.begin();
260 itr != remote_entries.end();
261 ++itr) {
262 const google_apis::ResourceEntry& remote_entry = **itr;
263 EXPECT_FALSE(ContainsKey(app_root_by_title, remote_entry.title()));
264 app_root_by_title[remote_entry.title()] = *itr;
267 for (std::map<std::string, CannedSyncableFileSystem*>::const_iterator itr =
268 file_systems_.begin();
269 itr != file_systems_.end(); ++itr) {
270 const std::string& app_id = itr->first;
271 SCOPED_TRACE(testing::Message() << "Verifying app: " << app_id);
272 CannedSyncableFileSystem* file_system = itr->second;
273 ASSERT_TRUE(ContainsKey(app_root_by_title, app_id));
274 VerifyConsistencyForFolder(
275 app_id, base::FilePath(),
276 app_root_by_title[app_id]->resource_id(),
277 file_system);
281 void VerifyConsistencyForFolder(const std::string& app_id,
282 const base::FilePath& path,
283 const std::string& folder_id,
284 CannedSyncableFileSystem* file_system) {
285 SCOPED_TRACE(testing::Message() << "Verifying folder: " << path.value());
287 ScopedVector<google_apis::ResourceEntry> remote_entries;
288 EXPECT_EQ(google_apis::HTTP_SUCCESS,
289 fake_drive_service_helper_->ListFilesInFolder(
290 folder_id, &remote_entries));
291 std::map<std::string, const google_apis::ResourceEntry*>
292 remote_entry_by_title;
293 for (ScopedVector<google_apis::ResourceEntry>::iterator itr =
294 remote_entries.begin();
295 itr != remote_entries.end();
296 ++itr) {
297 const google_apis::ResourceEntry& remote_entry = **itr;
298 EXPECT_FALSE(ContainsKey(remote_entry_by_title, remote_entry.title()));
299 remote_entry_by_title[remote_entry.title()] = *itr;
302 fileapi::FileSystemURL url(CreateURL(app_id, path));
303 CannedSyncableFileSystem::FileEntryList local_entries;
304 EXPECT_EQ(base::PLATFORM_FILE_OK,
305 file_system->ReadDirectory(url, &local_entries));
306 for (CannedSyncableFileSystem::FileEntryList::iterator itr =
307 local_entries.begin();
308 itr != local_entries.end();
309 ++itr) {
310 const fileapi::DirectoryEntry& local_entry = *itr;
311 fileapi::FileSystemURL entry_url(
312 CreateURL(app_id, path.Append(local_entry.name)));
313 std::string title = entry_url.path().AsUTF8Unsafe();
314 ASSERT_TRUE(ContainsKey(remote_entry_by_title, title));
315 const google_apis::ResourceEntry& remote_entry =
316 *remote_entry_by_title[title];
317 if (local_entry.is_directory) {
318 ASSERT_TRUE(remote_entry.is_folder());
319 VerifyConsistencyForFolder(app_id, entry_url.path(),
320 remote_entry.resource_id(),
321 file_system);
322 } else {
323 ASSERT_TRUE(remote_entry.is_file());
324 VerifyConsistencyForFile(app_id, entry_url.path(),
325 remote_entry.resource_id(),
326 file_system);
328 remote_entry_by_title.erase(title);
331 EXPECT_TRUE(remote_entry_by_title.empty());
334 void VerifyConsistencyForFile(const std::string& app_id,
335 const base::FilePath& path,
336 const std::string& file_id,
337 CannedSyncableFileSystem* file_system) {
338 fileapi::FileSystemURL url(CreateURL(app_id, path));
339 std::string file_content;
340 EXPECT_EQ(google_apis::HTTP_SUCCESS,
341 fake_drive_service_helper_->ReadFile(file_id, &file_content));
342 EXPECT_EQ(base::PLATFORM_FILE_OK,
343 file_system->VerifyFile(url, file_content));
346 drive::FakeDriveService* fake_drive_service() {
347 return static_cast<drive::FakeDriveService*>(
348 remote_sync_service_->GetDriveService());
351 drive::DriveUploaderInterface* drive_uploader() {
352 return remote_sync_service_->GetDriveUploader();
355 FakeDriveServiceHelper* fake_drive_service_helper() {
356 return fake_drive_service_helper_.get();
359 MetadataDatabase* metadata_database() {
360 return remote_sync_service_->GetMetadataDatabase();
363 private:
364 content::TestBrowserThreadBundle thread_bundle_;
366 base::ScopedTempDir base_dir_;
367 TestingProfile profile_;
369 scoped_ptr<SyncEngine> remote_sync_service_;
370 scoped_ptr<LocalFileSyncService> local_sync_service_;
372 scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
373 std::map<std::string, CannedSyncableFileSystem*> file_systems_;
376 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
377 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
379 DISALLOW_COPY_AND_ASSIGN(DriveBackendSyncTest);
382 TEST_F(DriveBackendSyncTest, LocalToRemoteBasicTest) {
383 std::string app_id = "example";
385 RegisterApp(app_id);
386 AddOrUpdateLocalFile(app_id, FPL("file"), "abcde");
388 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
389 VerifyConsistency();
392 TEST_F(DriveBackendSyncTest, RemoteToLocalBasicTest) {
393 std::string app_id = "example";
394 RegisterApp(app_id);
396 std::string app_root_folder_id;
397 EXPECT_TRUE(GetAppRootFolderID(app_id, &app_root_folder_id));
399 std::string file_id;
400 EXPECT_EQ(google_apis::HTTP_SUCCESS,
401 fake_drive_service_helper()->AddFile(
402 app_root_folder_id, "file", "abcde", &file_id));
404 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
405 VerifyConsistency();
408 TEST_F(DriveBackendSyncTest, LocalFileUpdateTest) {
409 std::string app_id = "example";
410 const base::FilePath::StringType kPath(FPL("file"));
412 RegisterApp(app_id);
413 AddOrUpdateLocalFile(app_id, kPath, "abcde");
415 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
416 VerifyConsistency();
418 UpdateLocalFile(app_id, kPath, "1234567890");
420 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
421 VerifyConsistency();
424 TEST_F(DriveBackendSyncTest, RemoteFileUpdateTest) {
425 std::string app_id = "example";
427 RegisterApp(app_id);
428 std::string remote_file_id;
429 std::string app_root_folder_id;
430 EXPECT_TRUE(GetAppRootFolderID(app_id, &app_root_folder_id));
431 EXPECT_EQ(google_apis::HTTP_SUCCESS,
432 fake_drive_service_helper()->AddFile(
433 app_root_folder_id, "file", "abcde", &remote_file_id));
435 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
436 VerifyConsistency();
438 EXPECT_EQ(google_apis::HTTP_SUCCESS,
439 fake_drive_service_helper()->UpdateFile(
440 remote_file_id, "1234567890"));
442 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
443 VerifyConsistency();
446 TEST_F(DriveBackendSyncTest, LocalFileDeletionTest) {
447 std::string app_id = "example";
448 const base::FilePath::StringType path(FPL("file"));
450 RegisterApp(app_id);
451 AddOrUpdateLocalFile(app_id, path, "abcde");
453 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
454 VerifyConsistency();
456 RemoveLocal(app_id, path);
458 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
459 VerifyConsistency();
462 TEST_F(DriveBackendSyncTest, RemoteFileDeletionTest) {
463 std::string app_id = "example";
464 const base::FilePath::StringType path(FPL("file"));
466 RegisterApp(app_id);
467 AddOrUpdateLocalFile(app_id, path, "abcde");
469 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
470 VerifyConsistency();
472 std::string file_id;
473 EXPECT_TRUE(GetFileIDByPath(app_id, base::FilePath(path), &file_id));
474 EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
475 fake_drive_service_helper()->DeleteResource(file_id));
477 EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
478 VerifyConsistency();
481 } // namespace drive_backend
482 } // namespace sync_file_system