Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / remote_to_local_syncer_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/remote_to_local_syncer.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/logging.h"
13 #include "base/run_loop.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_test_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/list_changes_task.h"
20 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
21 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
22 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
23 #include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
24 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
25 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
26 #include "content/public/test/test_browser_thread_bundle.h"
27 #include "google_apis/drive/gdata_errorcode.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29
30 namespace sync_file_system {
31 namespace drive_backend {
32
33 namespace {
34
35 fileapi::FileSystemURL URL(const GURL& origin,
36                            const std::string& path) {
37   return CreateSyncableFileSystemURL(
38       origin, base::FilePath::FromUTF8Unsafe(path));
39 }
40
41 }  // namespace
42
43 class RemoteToLocalSyncerTest : public testing::Test,
44                                 public SyncEngineContext {
45  public:
46   typedef FakeRemoteChangeProcessor::URLToFileChangesMap URLToFileChangesMap;
47
48   RemoteToLocalSyncerTest()
49       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
50   virtual ~RemoteToLocalSyncerTest() {}
51
52   virtual void SetUp() OVERRIDE {
53     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
54
55     fake_drive_service_.reset(new drive::FakeDriveService);
56     ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
57         "sync_file_system/account_metadata.json"));
58     ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
59         "gdata/empty_feed.json"));
60
61     drive_uploader_.reset(new drive::DriveUploader(
62         fake_drive_service_.get(), base::MessageLoopProxy::current().get()));
63     fake_drive_helper_.reset(new FakeDriveServiceHelper(
64         fake_drive_service_.get(), drive_uploader_.get(),
65         kSyncRootFolderTitle));
66     fake_remote_change_processor_.reset(new FakeRemoteChangeProcessor);
67
68     RegisterSyncableFileSystem();
69   }
70
71   virtual void TearDown() OVERRIDE {
72     RevokeSyncableFileSystem();
73
74     fake_remote_change_processor_.reset();
75     metadata_database_.reset();
76     fake_drive_helper_.reset();
77     drive_uploader_.reset();
78     fake_drive_service_.reset();
79     base::RunLoop().RunUntilIdle();
80   }
81
82   void InitializeMetadataDatabase() {
83     SyncEngineInitializer initializer(this,
84                                       base::MessageLoopProxy::current(),
85                                       fake_drive_service_.get(),
86                                       database_dir_.path());
87     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
88     initializer.Run(CreateResultReceiver(&status));
89     base::RunLoop().RunUntilIdle();
90     EXPECT_EQ(SYNC_STATUS_OK, status);
91     metadata_database_ = initializer.PassMetadataDatabase();
92   }
93
94   void RegisterApp(const std::string& app_id,
95                    const std::string& app_root_folder_id) {
96     SyncStatusCode status = SYNC_STATUS_FAILED;
97     metadata_database_->RegisterApp(app_id, app_root_folder_id,
98                                     CreateResultReceiver(&status));
99     base::RunLoop().RunUntilIdle();
100     EXPECT_EQ(SYNC_STATUS_OK, status);
101   }
102
103   virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
104     return fake_drive_service_.get();
105   }
106
107   virtual drive::DriveUploaderInterface* GetDriveUploader() OVERRIDE {
108     return drive_uploader_.get();
109   }
110
111   virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
112     return metadata_database_.get();
113   }
114
115   virtual RemoteChangeProcessor* GetRemoteChangeProcessor() OVERRIDE {
116     return fake_remote_change_processor_.get();
117   }
118
119   virtual base::SequencedTaskRunner* GetBlockingTaskRunner() OVERRIDE {
120     return base::MessageLoopProxy::current().get();
121   }
122
123  protected:
124   std::string CreateSyncRoot() {
125     std::string sync_root_folder_id;
126     EXPECT_EQ(google_apis::HTTP_CREATED,
127               fake_drive_helper_->AddOrphanedFolder(
128                   kSyncRootFolderTitle, &sync_root_folder_id));
129     return sync_root_folder_id;
130   }
131
132   std::string CreateRemoteFolder(const std::string& parent_folder_id,
133                                  const std::string& title) {
134     std::string folder_id;
135     EXPECT_EQ(google_apis::HTTP_CREATED,
136               fake_drive_helper_->AddFolder(
137                   parent_folder_id, title, &folder_id));
138     return folder_id;
139   }
140
141   std::string CreateRemoteFile(const std::string& parent_folder_id,
142                                const std::string& title,
143                                const std::string& content) {
144     std::string file_id;
145     EXPECT_EQ(google_apis::HTTP_SUCCESS,
146               fake_drive_helper_->AddFile(
147                   parent_folder_id, title, content, &file_id));
148     return file_id;
149   }
150
151   void DeleteRemoteFile(const std::string& file_id) {
152     EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
153               fake_drive_helper_->DeleteResource(file_id));
154   }
155
156   void CreateLocalFolder(const fileapi::FileSystemURL& url) {
157     fake_remote_change_processor_->UpdateLocalFileMetadata(
158         url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
159                         SYNC_FILE_TYPE_DIRECTORY));
160   }
161
162   void CreateLocalFile(const fileapi::FileSystemURL& url) {
163     fake_remote_change_processor_->UpdateLocalFileMetadata(
164         url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
165                         SYNC_FILE_TYPE_FILE));
166   }
167
168   SyncStatusCode RunSyncer() {
169     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
170     scoped_ptr<RemoteToLocalSyncer> syncer(new RemoteToLocalSyncer(this));
171     syncer->Run(CreateResultReceiver(&status));
172     base::RunLoop().RunUntilIdle();
173     return status;
174   }
175
176   void RunSyncerUntilIdle() {
177     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
178     while (status != SYNC_STATUS_NO_CHANGE_TO_SYNC)
179       status = RunSyncer();
180   }
181
182   SyncStatusCode ListChanges() {
183     ListChangesTask list_changes(this);
184     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
185     list_changes.Run(CreateResultReceiver(&status));
186     base::RunLoop().RunUntilIdle();
187     return status;
188   }
189
190   void AppendExpectedChange(const fileapi::FileSystemURL& url,
191                             FileChange::ChangeType change_type,
192                             SyncFileType file_type) {
193     expected_changes_[url].push_back(FileChange(change_type, file_type));
194   }
195
196   void VerifyConsistency() {
197     fake_remote_change_processor_->VerifyConsistency(expected_changes_);
198   }
199
200  private:
201   content::TestBrowserThreadBundle thread_bundle_;
202   base::ScopedTempDir database_dir_;
203
204   scoped_ptr<drive::FakeDriveService> fake_drive_service_;
205   scoped_ptr<drive::DriveUploader> drive_uploader_;
206   scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
207   scoped_ptr<MetadataDatabase> metadata_database_;
208   scoped_ptr<FakeRemoteChangeProcessor> fake_remote_change_processor_;
209
210   URLToFileChangesMap expected_changes_;
211
212   DISALLOW_COPY_AND_ASSIGN(RemoteToLocalSyncerTest);
213 };
214
215 TEST_F(RemoteToLocalSyncerTest, AddNewFile) {
216   const GURL kOrigin("chrome-extension://example");
217   const std::string sync_root = CreateSyncRoot();
218   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
219   InitializeMetadataDatabase();
220   RegisterApp(kOrigin.host(), app_root);
221
222   const std::string folder1 = CreateRemoteFolder(app_root, "folder1");
223   const std::string file1 = CreateRemoteFile(app_root, "file1", "data1");
224   const std::string folder2 = CreateRemoteFolder(folder1, "folder2");
225   const std::string file2 = CreateRemoteFile(folder1, "file2", "data2");
226
227   RunSyncerUntilIdle();
228
229   // Create expected changes.
230   // TODO(nhiroki): Clean up creating URL part.
231   AppendExpectedChange(URL(kOrigin, "folder1"),
232                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
233                        SYNC_FILE_TYPE_DIRECTORY);
234   AppendExpectedChange(URL(kOrigin, "file1"),
235                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
236                        SYNC_FILE_TYPE_FILE);
237   AppendExpectedChange(URL(kOrigin, "folder1/folder2"),
238                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
239                        SYNC_FILE_TYPE_DIRECTORY);
240   AppendExpectedChange(URL(kOrigin, "folder1/file2"),
241                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
242                        SYNC_FILE_TYPE_FILE);
243
244   VerifyConsistency();
245
246   EXPECT_FALSE(GetMetadataDatabase()->GetNormalPriorityDirtyTracker(NULL));
247   EXPECT_FALSE(GetMetadataDatabase()->GetLowPriorityDirtyTracker(NULL));
248 }
249
250 TEST_F(RemoteToLocalSyncerTest, DeleteFile) {
251   const GURL kOrigin("chrome-extension://example");
252   const std::string sync_root = CreateSyncRoot();
253   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
254   InitializeMetadataDatabase();
255   RegisterApp(kOrigin.host(), app_root);
256
257   const std::string folder = CreateRemoteFolder(app_root, "folder");
258   const std::string file = CreateRemoteFile(app_root, "file", "data");
259
260   AppendExpectedChange(URL(kOrigin, "folder"),
261                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
262                        SYNC_FILE_TYPE_DIRECTORY);
263   AppendExpectedChange(URL(kOrigin, "file"),
264                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
265                        SYNC_FILE_TYPE_FILE);
266
267   RunSyncerUntilIdle();
268   VerifyConsistency();
269
270   DeleteRemoteFile(folder);
271   DeleteRemoteFile(file);
272
273   AppendExpectedChange(URL(kOrigin, "folder"),
274                        FileChange::FILE_CHANGE_DELETE,
275                        SYNC_FILE_TYPE_UNKNOWN);
276   AppendExpectedChange(URL(kOrigin, "file"),
277                        FileChange::FILE_CHANGE_DELETE,
278                        SYNC_FILE_TYPE_UNKNOWN);
279
280   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
281   RunSyncerUntilIdle();
282   VerifyConsistency();
283
284   EXPECT_FALSE(GetMetadataDatabase()->GetNormalPriorityDirtyTracker(NULL));
285   EXPECT_FALSE(GetMetadataDatabase()->GetLowPriorityDirtyTracker(NULL));
286 }
287
288 TEST_F(RemoteToLocalSyncerTest, DeleteNestedFiles) {
289   const GURL kOrigin("chrome-extension://example");
290   const std::string sync_root = CreateSyncRoot();
291   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
292   InitializeMetadataDatabase();
293   RegisterApp(kOrigin.host(), app_root);
294
295   const std::string folder1 = CreateRemoteFolder(app_root, "folder1");
296   const std::string file1 = CreateRemoteFile(app_root, "file1", "data1");
297   const std::string folder2 = CreateRemoteFolder(folder1, "folder2");
298   const std::string file2 = CreateRemoteFile(folder1, "file2", "data2");
299
300   AppendExpectedChange(URL(kOrigin, "folder1"),
301                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
302                        SYNC_FILE_TYPE_DIRECTORY);
303   AppendExpectedChange(URL(kOrigin, "file1"),
304                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
305                        SYNC_FILE_TYPE_FILE);
306   AppendExpectedChange(URL(kOrigin, "folder1/folder2"),
307                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
308                        SYNC_FILE_TYPE_DIRECTORY);
309   AppendExpectedChange(URL(kOrigin, "folder1/file2"),
310                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
311                        SYNC_FILE_TYPE_FILE);
312
313   RunSyncerUntilIdle();
314   VerifyConsistency();
315
316   DeleteRemoteFile(folder1);
317
318   AppendExpectedChange(URL(kOrigin, "folder1"),
319                        FileChange::FILE_CHANGE_DELETE,
320                        SYNC_FILE_TYPE_UNKNOWN);
321   // Changes for descendant files ("folder2" and "file2") should be ignored.
322
323   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
324   RunSyncerUntilIdle();
325   VerifyConsistency();
326
327   EXPECT_FALSE(GetMetadataDatabase()->GetNormalPriorityDirtyTracker(NULL));
328   EXPECT_FALSE(GetMetadataDatabase()->GetLowPriorityDirtyTracker(NULL));
329 }
330
331 TEST_F(RemoteToLocalSyncerTest, Conflict_CreateFileOnFolder) {
332   const GURL kOrigin("chrome-extension://example");
333   const std::string sync_root = CreateSyncRoot();
334   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
335   InitializeMetadataDatabase();
336   RegisterApp(kOrigin.host(), app_root);
337
338   CreateLocalFolder(URL(kOrigin, "folder"));
339   CreateRemoteFile(app_root, "folder", "data");
340
341   // Folder-File conflict happens. File creation should be ignored.
342
343   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
344   RunSyncerUntilIdle();
345   VerifyConsistency();
346
347   // Tracker for the remote file should be lowered.
348   EXPECT_FALSE(GetMetadataDatabase()->GetNormalPriorityDirtyTracker(NULL));
349   EXPECT_TRUE(GetMetadataDatabase()->GetLowPriorityDirtyTracker(NULL));
350 }
351
352 TEST_F(RemoteToLocalSyncerTest, Conflict_CreateFolderOnFile) {
353   const GURL kOrigin("chrome-extension://example");
354   const std::string sync_root = CreateSyncRoot();
355   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
356   InitializeMetadataDatabase();
357   RegisterApp(kOrigin.host(), app_root);
358
359   RunSyncerUntilIdle();
360   VerifyConsistency();
361
362   CreateLocalFile(URL(kOrigin, "file"));
363   CreateRemoteFolder(app_root, "file");
364
365   // File-Folder conflict happens. Folder should override the existing file.
366   AppendExpectedChange(URL(kOrigin, "file"),
367                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
368                        SYNC_FILE_TYPE_DIRECTORY);
369
370   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
371   RunSyncerUntilIdle();
372   VerifyConsistency();
373
374   EXPECT_FALSE(GetMetadataDatabase()->GetNormalPriorityDirtyTracker(NULL));
375   EXPECT_FALSE(GetMetadataDatabase()->GetLowPriorityDirtyTracker(NULL));
376 }
377
378 TEST_F(RemoteToLocalSyncerTest, Conflict_CreateFolderOnFolder) {
379   const GURL kOrigin("chrome-extension://example");
380   const std::string sync_root = CreateSyncRoot();
381   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
382   InitializeMetadataDatabase();
383   RegisterApp(kOrigin.host(), app_root);
384
385   CreateLocalFolder(URL(kOrigin, "folder"));
386   CreateRemoteFolder(app_root, "folder");
387
388   // Folder-Folder conflict happens. Folder creation should be ignored.
389
390   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
391   RunSyncerUntilIdle();
392   VerifyConsistency();
393
394   EXPECT_FALSE(GetMetadataDatabase()->GetNormalPriorityDirtyTracker(NULL));
395   EXPECT_FALSE(GetMetadataDatabase()->GetLowPriorityDirtyTracker(NULL));
396 }
397
398 TEST_F(RemoteToLocalSyncerTest, Conflict_CreateFileOnFile) {
399   const GURL kOrigin("chrome-extension://example");
400   const std::string sync_root = CreateSyncRoot();
401   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
402   InitializeMetadataDatabase();
403   RegisterApp(kOrigin.host(), app_root);
404
405   CreateLocalFile(URL(kOrigin, "file"));
406   CreateRemoteFile(app_root, "file", "data");
407
408   // File-File conflict happens. File creation should be ignored.
409
410   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
411   RunSyncerUntilIdle();
412   VerifyConsistency();
413
414   // Tracker for the remote file should be lowered.
415   EXPECT_FALSE(GetMetadataDatabase()->GetNormalPriorityDirtyTracker(NULL));
416   EXPECT_TRUE(GetMetadataDatabase()->GetLowPriorityDirtyTracker(NULL));
417 }
418
419 TEST_F(RemoteToLocalSyncerTest, Conflict_CreateNestedFolderOnFile) {
420   const GURL kOrigin("chrome-extension://example");
421   const std::string sync_root = CreateSyncRoot();
422   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
423   InitializeMetadataDatabase();
424   RegisterApp(kOrigin.host(), app_root);
425
426   RunSyncerUntilIdle();
427   VerifyConsistency();
428
429   const std::string folder = CreateRemoteFolder(app_root, "folder");
430   CreateLocalFile(URL(kOrigin, "/folder"));
431   CreateRemoteFile(folder, "file", "data");
432
433   // File-Folder conflict happens. Folder should override the existing file.
434   AppendExpectedChange(URL(kOrigin, "/folder"),
435                        FileChange::FILE_CHANGE_ADD_OR_UPDATE,
436                        SYNC_FILE_TYPE_DIRECTORY);
437
438   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
439   RunSyncerUntilIdle();
440   VerifyConsistency();
441 }
442
443 TEST_F(RemoteToLocalSyncerTest, AppRootDeletion) {
444   const GURL kOrigin("chrome-extension://example");
445   const std::string sync_root = CreateSyncRoot();
446   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
447   InitializeMetadataDatabase();
448   RegisterApp(kOrigin.host(), app_root);
449
450   RunSyncerUntilIdle();
451   VerifyConsistency();
452
453   DeleteRemoteFile(app_root);
454
455   AppendExpectedChange(URL(kOrigin, "/"),
456                        FileChange::FILE_CHANGE_DELETE,
457                        SYNC_FILE_TYPE_UNKNOWN);
458
459   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
460   RunSyncerUntilIdle();
461   VerifyConsistency();
462
463   // SyncEngine will re-register the app and resurrect the app root later.
464 }
465
466 }  // namespace drive_backend
467 }  // namespace sync_file_system