Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / local_to_remote_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/local_to_remote_syncer.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/logging.h"
11 #include "base/run_loop.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chrome/browser/drive/drive_api_util.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/fake_drive_uploader.h"
20 #include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h"
21 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
22 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
23 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
24 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
25 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
26 #include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
27 #include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
28 #include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
29 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
30 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
31 #include "content/public/test/test_browser_thread_bundle.h"
32 #include "google_apis/drive/drive_api_parser.h"
33 #include "google_apis/drive/gdata_errorcode.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
36 #include "third_party/leveldatabase/src/include/leveldb/env.h"
37
38 namespace sync_file_system {
39 namespace drive_backend {
40
41 namespace {
42
43 storage::FileSystemURL URL(const GURL& origin, const std::string& path) {
44   return CreateSyncableFileSystemURL(
45       origin, base::FilePath::FromUTF8Unsafe(path));
46 }
47
48 const int kRetryLimit = 100;
49
50 }  // namespace
51
52 class LocalToRemoteSyncerTest : public testing::Test {
53  public:
54   LocalToRemoteSyncerTest()
55       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
56   virtual ~LocalToRemoteSyncerTest() {}
57
58   virtual void SetUp() OVERRIDE {
59     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
60     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
61
62     scoped_ptr<FakeDriveServiceWrapper>
63         fake_drive_service(new FakeDriveServiceWrapper);
64     scoped_ptr<drive::DriveUploaderInterface>
65         drive_uploader(new FakeDriveUploader(fake_drive_service.get()));
66     fake_drive_helper_.reset(new FakeDriveServiceHelper(
67         fake_drive_service.get(),
68         drive_uploader.get(),
69         kSyncRootFolderTitle));
70     remote_change_processor_.reset(new FakeRemoteChangeProcessor);
71
72     context_.reset(new SyncEngineContext(
73         fake_drive_service.PassAs<drive::DriveServiceInterface>(),
74         drive_uploader.Pass(),
75         NULL,
76         base::ThreadTaskRunnerHandle::Get(),
77         base::ThreadTaskRunnerHandle::Get()));
78     context_->SetRemoteChangeProcessor(remote_change_processor_.get());
79
80     RegisterSyncableFileSystem();
81
82     sync_task_manager_.reset(new SyncTaskManager(
83         base::WeakPtr<SyncTaskManager::Client>(),
84         10 /* maximum_background_task */,
85         base::ThreadTaskRunnerHandle::Get()));
86     sync_task_manager_->Initialize(SYNC_STATUS_OK);
87   }
88
89   virtual void TearDown() OVERRIDE {
90     sync_task_manager_.reset();
91     RevokeSyncableFileSystem();
92     fake_drive_helper_.reset();
93     context_.reset();
94     base::RunLoop().RunUntilIdle();
95   }
96
97   void InitializeMetadataDatabase() {
98     SyncEngineInitializer* initializer =
99         new SyncEngineInitializer(context_.get(),
100                                   database_dir_.path(),
101                                   in_memory_env_.get());
102     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
103
104     sync_task_manager_->ScheduleSyncTask(
105         FROM_HERE,
106         scoped_ptr<SyncTask>(initializer),
107         SyncTaskManager::PRIORITY_MED,
108         base::Bind(&LocalToRemoteSyncerTest::DidInitializeMetadataDatabase,
109                    base::Unretained(this), initializer, &status));
110
111     base::RunLoop().RunUntilIdle();
112     EXPECT_EQ(SYNC_STATUS_OK, status);
113   }
114
115   void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer,
116                                      SyncStatusCode* status_out,
117                                      SyncStatusCode status) {
118     *status_out = status;
119     context_->SetMetadataDatabase(initializer->PassMetadataDatabase());
120   }
121
122   void RegisterApp(const std::string& app_id,
123                    const std::string& app_root_folder_id) {
124     SyncStatusCode status = context_->GetMetadataDatabase()->RegisterApp(
125         app_id, app_root_folder_id);
126     EXPECT_EQ(SYNC_STATUS_OK, status);
127   }
128
129   MetadataDatabase* GetMetadataDatabase() {
130     return context_->GetMetadataDatabase();
131   }
132
133  protected:
134   std::string CreateSyncRoot() {
135     std::string sync_root_folder_id;
136     EXPECT_EQ(google_apis::HTTP_CREATED,
137               fake_drive_helper_->AddOrphanedFolder(
138                   kSyncRootFolderTitle, &sync_root_folder_id));
139     return sync_root_folder_id;
140   }
141
142   std::string CreateRemoteFolder(const std::string& parent_folder_id,
143                                  const std::string& title) {
144     std::string folder_id;
145     EXPECT_EQ(google_apis::HTTP_CREATED,
146               fake_drive_helper_->AddFolder(
147                   parent_folder_id, title, &folder_id));
148     return folder_id;
149   }
150
151   std::string CreateRemoteFile(const std::string& parent_folder_id,
152                                const std::string& title,
153                                const std::string& content) {
154     std::string file_id;
155     EXPECT_EQ(google_apis::HTTP_SUCCESS,
156               fake_drive_helper_->AddFile(
157                   parent_folder_id, title, content, &file_id));
158     return file_id;
159   }
160
161   void DeleteResource(const std::string& file_id) {
162     EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
163               fake_drive_helper_->DeleteResource(file_id));
164   }
165
166   SyncStatusCode RunLocalToRemoteSyncer(FileChange file_change,
167                                         const storage::FileSystemURL& url) {
168     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
169     base::FilePath local_path = base::FilePath::FromUTF8Unsafe("dummy");
170     scoped_ptr<LocalToRemoteSyncer> syncer(new LocalToRemoteSyncer(
171         context_.get(),
172         SyncFileMetadata(file_change.file_type(), 0, base::Time()),
173         file_change, local_path, url));
174     syncer->RunPreflight(SyncTaskToken::CreateForTesting(
175         CreateResultReceiver(&status)));
176     base::RunLoop().RunUntilIdle();
177     return status;
178   }
179
180   SyncStatusCode ListChanges() {
181     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
182     sync_task_manager_->ScheduleSyncTask(
183         FROM_HERE,
184         scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
185         SyncTaskManager::PRIORITY_MED,
186         CreateResultReceiver(&status));
187     base::RunLoop().RunUntilIdle();
188     return status;
189   }
190
191   SyncStatusCode RunRemoteToLocalSyncer() {
192     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
193     scoped_ptr<RemoteToLocalSyncer>
194         syncer(new RemoteToLocalSyncer(context_.get()));
195     syncer->RunPreflight(SyncTaskToken::CreateForTesting(
196         CreateResultReceiver(&status)));
197     base::RunLoop().RunUntilIdle();
198     return status;
199   }
200
201   SyncStatusCode RunRemoteToLocalSyncerUntilIdle() {
202     SyncStatusCode status;
203     int retry_count = 0;
204     do {
205       if (retry_count++ > kRetryLimit)
206         break;
207       status = RunRemoteToLocalSyncer();
208     } while (status == SYNC_STATUS_OK ||
209              status == SYNC_STATUS_RETRY ||
210              GetMetadataDatabase()->PromoteDemotedTrackers());
211     EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC, status);
212     return status;
213   }
214
215   ScopedVector<google_apis::ResourceEntry>
216   GetResourceEntriesForParentAndTitle(const std::string& parent_folder_id,
217                                       const std::string& title) {
218     ScopedVector<google_apis::ResourceEntry> entries;
219     EXPECT_EQ(google_apis::HTTP_SUCCESS,
220               fake_drive_helper_->SearchByTitle(
221                   parent_folder_id, title, &entries));
222     return entries.Pass();
223   }
224
225   std::string GetFileIDForParentAndTitle(const std::string& parent_folder_id,
226                                          const std::string& title) {
227     ScopedVector<google_apis::ResourceEntry> entries =
228         GetResourceEntriesForParentAndTitle(parent_folder_id, title);
229     if (entries.size() != 1)
230       return std::string();
231     return entries[0]->resource_id();
232   }
233
234   void VerifyTitleUniqueness(
235       const std::string& parent_folder_id,
236       const std::string& title,
237       google_apis::ResourceEntry::ResourceEntryKind kind) {
238     ScopedVector<google_apis::ResourceEntry> entries;
239     EXPECT_EQ(google_apis::HTTP_SUCCESS,
240               fake_drive_helper_->SearchByTitle(
241                   parent_folder_id, title, &entries));
242     ASSERT_EQ(1u, entries.size());
243     EXPECT_EQ(kind, entries[0]->kind());
244   }
245
246   void VerifyFileDeletion(const std::string& parent_folder_id,
247                           const std::string& title) {
248     ScopedVector<google_apis::ResourceEntry> entries;
249     EXPECT_EQ(google_apis::HTTP_SUCCESS,
250               fake_drive_helper_->SearchByTitle(
251                   parent_folder_id, title, &entries));
252     EXPECT_TRUE(entries.empty());
253   }
254
255  private:
256   content::TestBrowserThreadBundle thread_bundle_;
257   base::ScopedTempDir database_dir_;
258   scoped_ptr<leveldb::Env> in_memory_env_;
259
260   scoped_ptr<SyncEngineContext> context_;
261   scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
262   scoped_ptr<FakeRemoteChangeProcessor> remote_change_processor_;
263   scoped_ptr<SyncTaskManager> sync_task_manager_;
264
265   DISALLOW_COPY_AND_ASSIGN(LocalToRemoteSyncerTest);
266 };
267
268 TEST_F(LocalToRemoteSyncerTest, CreateFile) {
269   const GURL kOrigin("chrome-extension://example");
270   const std::string sync_root = CreateSyncRoot();
271   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
272   InitializeMetadataDatabase();
273   RegisterApp(kOrigin.host(), app_root);
274
275   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
276       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
277                  SYNC_FILE_TYPE_FILE),
278       URL(kOrigin, "file1")));
279   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
280       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
281                  SYNC_FILE_TYPE_DIRECTORY),
282       URL(kOrigin, "folder")));
283   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
284       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
285                  SYNC_FILE_TYPE_FILE),
286       URL(kOrigin, "folder/file2")));
287
288   std::string folder_id = GetFileIDForParentAndTitle(app_root, "folder");
289   ASSERT_FALSE(folder_id.empty());
290
291   VerifyTitleUniqueness(
292       app_root, "file1", google_apis::ResourceEntry::ENTRY_KIND_FILE);
293   VerifyTitleUniqueness(
294       app_root, "folder", google_apis::ResourceEntry::ENTRY_KIND_FOLDER);
295   VerifyTitleUniqueness(
296       folder_id, "file2", google_apis::ResourceEntry::ENTRY_KIND_FILE);
297 }
298
299 TEST_F(LocalToRemoteSyncerTest, CreateFileOnMissingPath) {
300   const GURL kOrigin("chrome-extension://example");
301   const std::string sync_root = CreateSyncRoot();
302   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
303   InitializeMetadataDatabase();
304   RegisterApp(kOrigin.host(), app_root);
305
306   // Run the syncer 3 times to create missing folder1 and folder2.
307   EXPECT_EQ(SYNC_STATUS_RETRY, RunLocalToRemoteSyncer(
308       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
309                  SYNC_FILE_TYPE_FILE),
310       URL(kOrigin, "folder1/folder2/file")));
311   EXPECT_EQ(SYNC_STATUS_RETRY, RunLocalToRemoteSyncer(
312       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
313                  SYNC_FILE_TYPE_FILE),
314       URL(kOrigin, "folder1/folder2/file")));
315   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
316       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
317                  SYNC_FILE_TYPE_FILE),
318       URL(kOrigin, "folder1/folder2/file")));
319
320   std::string folder_id1 = GetFileIDForParentAndTitle(app_root, "folder1");
321   ASSERT_FALSE(folder_id1.empty());
322   std::string folder_id2 = GetFileIDForParentAndTitle(folder_id1, "folder2");
323   ASSERT_FALSE(folder_id2.empty());
324
325   VerifyTitleUniqueness(
326       app_root, "folder1", google_apis::ResourceEntry::ENTRY_KIND_FOLDER);
327   VerifyTitleUniqueness(
328       folder_id1, "folder2", google_apis::ResourceEntry::ENTRY_KIND_FOLDER);
329   VerifyTitleUniqueness(
330       folder_id2, "file", google_apis::ResourceEntry::ENTRY_KIND_FILE);
331 }
332
333 TEST_F(LocalToRemoteSyncerTest, DeleteFile) {
334   const GURL kOrigin("chrome-extension://example");
335   const std::string sync_root = CreateSyncRoot();
336   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
337   InitializeMetadataDatabase();
338   RegisterApp(kOrigin.host(), app_root);
339
340   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
341       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
342                  SYNC_FILE_TYPE_FILE),
343       URL(kOrigin, "file")));
344   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
345       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
346                  SYNC_FILE_TYPE_DIRECTORY),
347       URL(kOrigin, "folder")));
348
349   VerifyTitleUniqueness(
350       app_root, "file", google_apis::ResourceEntry::ENTRY_KIND_FILE);
351   VerifyTitleUniqueness(
352       app_root, "folder", google_apis::ResourceEntry::ENTRY_KIND_FOLDER);
353
354   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
355       FileChange(FileChange::FILE_CHANGE_DELETE,
356                  SYNC_FILE_TYPE_FILE),
357       URL(kOrigin, "file")));
358   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
359       FileChange(FileChange::FILE_CHANGE_DELETE,
360                  SYNC_FILE_TYPE_DIRECTORY),
361       URL(kOrigin, "folder")));
362
363   VerifyFileDeletion(app_root, "file");
364   VerifyFileDeletion(app_root, "folder");
365 }
366
367 TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFileOnFolder) {
368   const GURL kOrigin("chrome-extension://example");
369   const std::string sync_root = CreateSyncRoot();
370   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
371   InitializeMetadataDatabase();
372   RegisterApp(kOrigin.host(), app_root);
373
374   CreateRemoteFolder(app_root, "foo");
375   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
376   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
377       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
378                  SYNC_FILE_TYPE_FILE),
379       URL(kOrigin, "foo")));
380
381   // There should exist both file and folder on remote.
382   ScopedVector<google_apis::ResourceEntry> entries =
383       GetResourceEntriesForParentAndTitle(app_root, "foo");
384   ASSERT_EQ(2u, entries.size());
385   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FOLDER, entries[0]->kind());
386   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FILE, entries[1]->kind());
387 }
388
389 TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFolderOnFile) {
390   const GURL kOrigin("chrome-extension://example");
391   const std::string sync_root = CreateSyncRoot();
392   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
393   InitializeMetadataDatabase();
394   RegisterApp(kOrigin.host(), app_root);
395
396   CreateRemoteFile(app_root, "foo", "data");
397   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
398
399   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
400       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
401                  SYNC_FILE_TYPE_DIRECTORY),
402       URL(kOrigin, "foo")));
403
404   // There should exist both file and folder on remote.
405   ScopedVector<google_apis::ResourceEntry> entries =
406       GetResourceEntriesForParentAndTitle(app_root, "foo");
407   ASSERT_EQ(2u, entries.size());
408   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FILE, entries[0]->kind());
409   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FOLDER, entries[1]->kind());
410 }
411
412 TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFileOnFile) {
413   const GURL kOrigin("chrome-extension://example");
414   const std::string sync_root = CreateSyncRoot();
415   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
416   InitializeMetadataDatabase();
417   RegisterApp(kOrigin.host(), app_root);
418
419   CreateRemoteFile(app_root, "foo", "data");
420   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
421
422   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
423       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
424                  SYNC_FILE_TYPE_FILE),
425       URL(kOrigin, "foo")));
426
427   // There should exist both files on remote.
428   ScopedVector<google_apis::ResourceEntry> entries =
429       GetResourceEntriesForParentAndTitle(app_root, "foo");
430   ASSERT_EQ(2u, entries.size());
431   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FILE, entries[0]->kind());
432   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FILE, entries[1]->kind());
433 }
434
435 TEST_F(LocalToRemoteSyncerTest, Conflict_UpdateDeleteOnFile) {
436   const GURL kOrigin("chrome-extension://example");
437   const std::string sync_root = CreateSyncRoot();
438   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
439   InitializeMetadataDatabase();
440   RegisterApp(kOrigin.host(), app_root);
441
442   const std::string file_id = CreateRemoteFile(app_root, "foo", "data");
443   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
444   EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC,
445             RunRemoteToLocalSyncerUntilIdle());
446
447   DeleteResource(file_id);
448
449   EXPECT_EQ(SYNC_STATUS_FILE_BUSY, RunLocalToRemoteSyncer(
450       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
451                  SYNC_FILE_TYPE_FILE),
452       URL(kOrigin, "foo")));
453   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
454       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
455                  SYNC_FILE_TYPE_FILE),
456       URL(kOrigin, "foo")));
457
458   ScopedVector<google_apis::ResourceEntry> entries =
459       GetResourceEntriesForParentAndTitle(app_root, "foo");
460   ASSERT_EQ(1u, entries.size());
461   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FILE, entries[0]->kind());
462   EXPECT_TRUE(!entries[0]->deleted());
463   EXPECT_NE(file_id, entries[0]->resource_id());
464 }
465
466 TEST_F(LocalToRemoteSyncerTest, Conflict_CreateDeleteOnFile) {
467   const GURL kOrigin("chrome-extension://example");
468   const std::string sync_root = CreateSyncRoot();
469   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
470   InitializeMetadataDatabase();
471   RegisterApp(kOrigin.host(), app_root);
472
473   const std::string file_id = CreateRemoteFile(app_root, "foo", "data");
474   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
475   EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC,
476             RunRemoteToLocalSyncerUntilIdle());
477
478   DeleteResource(file_id);
479
480   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
481
482   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
483       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
484                  SYNC_FILE_TYPE_FILE),
485       URL(kOrigin, "foo")));
486
487   ScopedVector<google_apis::ResourceEntry> entries =
488       GetResourceEntriesForParentAndTitle(app_root, "foo");
489   ASSERT_EQ(1u, entries.size());
490   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FILE, entries[0]->kind());
491   EXPECT_TRUE(!entries[0]->deleted());
492   EXPECT_NE(file_id, entries[0]->resource_id());
493 }
494
495 TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFolderOnFolder) {
496   const GURL kOrigin("chrome-extension://example");
497   const std::string sync_root = CreateSyncRoot();
498   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
499   InitializeMetadataDatabase();
500   RegisterApp(kOrigin.host(), app_root);
501
502   const std::string folder_id = CreateRemoteFolder(app_root, "foo");
503
504   EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer(
505       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
506                  SYNC_FILE_TYPE_DIRECTORY),
507       URL(kOrigin, "foo")));
508
509   ScopedVector<google_apis::ResourceEntry> entries =
510       GetResourceEntriesForParentAndTitle(app_root, "foo");
511   ASSERT_EQ(2u, entries.size());
512   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FOLDER, entries[0]->kind());
513   EXPECT_EQ(google_apis::ResourceEntry::ENTRY_KIND_FOLDER, entries[1]->kind());
514   EXPECT_TRUE(!entries[0]->deleted());
515   EXPECT_TRUE(!entries[1]->deleted());
516   EXPECT_TRUE(folder_id == entries[0]->resource_id() ||
517               folder_id == entries[1]->resource_id());
518
519   TrackerIDSet trackers;
520   EXPECT_TRUE(GetMetadataDatabase()->FindTrackersByFileID(
521       folder_id, &trackers));
522   EXPECT_EQ(1u, trackers.size());
523   ASSERT_TRUE(trackers.has_active());
524 }
525
526 TEST_F(LocalToRemoteSyncerTest, AppRootDeletion) {
527   const GURL kOrigin("chrome-extension://example");
528   const std::string sync_root = CreateSyncRoot();
529   const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host());
530   InitializeMetadataDatabase();
531   RegisterApp(kOrigin.host(), app_root);
532
533   DeleteResource(app_root);
534   EXPECT_EQ(SYNC_STATUS_OK, ListChanges());
535   EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC,
536             RunRemoteToLocalSyncerUntilIdle());
537
538   EXPECT_EQ(SYNC_STATUS_UNKNOWN_ORIGIN, RunLocalToRemoteSyncer(
539       FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
540                  SYNC_FILE_TYPE_DIRECTORY),
541       URL(kOrigin, "foo")));
542
543   // SyncEngine will re-register the app and resurrect the app root later.
544 }
545
546 }  // namespace drive_backend
547 }  // namespace sync_file_system