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