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_v1/drive_file_sync_service.h"
6
7#include <utility>
8
9#include "base/command_line.h"
10#include "base/file_util.h"
11#include "base/message_loop/message_loop_proxy.h"
12#include "base/run_loop.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/extensions/test_extension_service.h"
17#include "chrome/browser/extensions/test_extension_system.h"
18#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
19#include "chrome/browser/sync_file_system/drive_backend_v1/api_util.h"
20#include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_util.h"
21#include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h"
22#include "chrome/browser/sync_file_system/file_status_observer.h"
23#include "chrome/browser/sync_file_system/mock_remote_change_processor.h"
24#include "chrome/browser/sync_file_system/sync_direction.h"
25#include "chrome/browser/sync_file_system/sync_file_metadata.h"
26#include "chrome/browser/sync_file_system/sync_file_system.pb.h"
27#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
28#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
29#include "chrome/test/base/testing_browser_process.h"
30#include "chrome/test/base/testing_profile.h"
31#include "chrome/test/base/testing_profile_manager.h"
32#include "content/public/test/test_browser_thread_bundle.h"
33#include "extensions/common/extension.h"
34#include "extensions/common/extension_builder.h"
35#include "extensions/common/id_util.h"
36#include "google_apis/drive/drive_api_parser.h"
37#include "google_apis/drive/gdata_errorcode.h"
38#include "google_apis/drive/gdata_wapi_parser.h"
39#include "google_apis/drive/test_util.h"
40#include "testing/gmock/include/gmock/gmock.h"
41#include "testing/gtest/include/gtest/gtest.h"
42#include "webkit/common/fileapi/file_system_util.h"
43
44#if defined(OS_CHROMEOS)
45#include "chrome/browser/chromeos/login/users/user_manager.h"
46#include "chrome/browser/chromeos/settings/cros_settings.h"
47#include "chrome/browser/chromeos/settings/device_settings_service.h"
48#endif
49
50#define FPL(x) FILE_PATH_LITERAL(x)
51
52using ::testing::StrictMock;
53using ::testing::_;
54
55using drive::DriveServiceInterface;
56using drive::DriveUploader;
57using drive::DriveUploaderInterface;
58using drive::FakeDriveService;
59
60using extensions::Extension;
61using extensions::DictionaryBuilder;
62using google_apis::FileResource;
63using google_apis::GDataErrorCode;
64
65namespace sync_file_system {
66
67using drive_backend::APIUtil;
68using drive_backend::APIUtilInterface;
69using drive_backend::FakeDriveServiceHelper;
70
71namespace {
72
73const char kTestProfileName[] = "test-profile";
74
75#if !defined(OS_ANDROID)
76const char kExtensionName1[] = "example1";
77const char kExtensionName2[] = "example2";
78#endif
79
80void DidInitialize(bool* done, SyncStatusCode status, bool created) {
81  EXPECT_FALSE(*done);
82  *done = true;
83  EXPECT_EQ(SYNC_STATUS_OK, status);
84  EXPECT_TRUE(created);
85}
86
87// Mocks adding an installed extension to ExtensionService.
88scoped_refptr<const extensions::Extension> AddTestExtension(
89    ExtensionService* extension_service,
90    const base::FilePath::StringType& extension_name) {
91  std::string id = extensions::id_util::GenerateIdForPath(
92      base::FilePath(extension_name));
93
94  scoped_refptr<const Extension> extension =
95      extensions::ExtensionBuilder().SetManifest(
96          DictionaryBuilder()
97            .Set("name", extension_name)
98            .Set("version", "1.0"))
99          .SetID(id)
100      .Build();
101  extension_service->AddExtension(extension.get());
102  return extension;
103}
104
105// Converts extension_name to extension ID.
106std::string ExtensionNameToId(const std::string& extension_name) {
107  base::FilePath path = base::FilePath::FromUTF8Unsafe(extension_name);
108  return extensions::id_util::GenerateIdForPath(path);
109}
110
111// Converts extension_name to GURL version.
112GURL ExtensionNameToGURL(const std::string& extension_name) {
113  return extensions::Extension::GetBaseURLFromExtensionId(
114      ExtensionNameToId(extension_name));
115}
116
117#if !defined(OS_ANDROID)
118ACTION(InvokeCompletionCallback) {
119  base::MessageLoopProxy::current()->PostTask(FROM_HERE, arg2);
120}
121
122ACTION(PrepareForRemoteChange_Busy) {
123  base::MessageLoopProxy::current()->PostTask(
124      FROM_HERE,
125      base::Bind(arg1,
126                 SYNC_STATUS_FILE_BUSY,
127                 SyncFileMetadata(),
128                 FileChangeList()));
129}
130
131ACTION(PrepareForRemoteChange_NotFound) {
132  base::MessageLoopProxy::current()->PostTask(
133      FROM_HERE,
134      base::Bind(arg1,
135                 SYNC_STATUS_OK,
136                 SyncFileMetadata(SYNC_FILE_TYPE_UNKNOWN, 0, base::Time()),
137                 FileChangeList()));
138}
139
140ACTION(PrepareForRemoteChange_NotModified) {
141  base::MessageLoopProxy::current()->PostTask(
142      FROM_HERE,
143      base::Bind(arg1,
144                 SYNC_STATUS_OK,
145                 SyncFileMetadata(SYNC_FILE_TYPE_FILE, 0, base::Time()),
146                 FileChangeList()));
147}
148
149ACTION(InvokeDidApplyRemoteChange) {
150  base::MessageLoopProxy::current()->PostTask(
151      FROM_HERE, base::Bind(arg3, SYNC_STATUS_OK));
152}
153#endif  // !defined(OS_ANDROID)
154
155}  // namespace
156
157class MockFileStatusObserver: public FileStatusObserver {
158 public:
159  MockFileStatusObserver() {}
160  virtual ~MockFileStatusObserver() {}
161
162  MOCK_METHOD4(OnFileStatusChanged,
163               void(const fileapi::FileSystemURL& url,
164                    SyncFileStatus sync_status,
165                    SyncAction action_taken,
166                    SyncDirection direction));
167};
168
169class DriveFileSyncServiceFakeTest : public testing::Test {
170 public:
171  DriveFileSyncServiceFakeTest()
172      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
173        profile_manager_(TestingBrowserProcess::GetGlobal()),
174        fake_drive_service_(NULL) {
175  }
176
177  virtual void SetUp() OVERRIDE {
178    ASSERT_TRUE(profile_manager_.SetUp());
179    profile_ = profile_manager_.CreateTestingProfile(kTestProfileName);
180
181    // Add TestExtensionSystem with registered ExtensionIds used in tests.
182    extensions::TestExtensionSystem* extension_system(
183        static_cast<extensions::TestExtensionSystem*>(
184            extensions::ExtensionSystem::Get(profile_)));
185    extension_system->CreateExtensionService(
186        CommandLine::ForCurrentProcess(), base::FilePath(), false);
187    extension_service_ = extension_system->Get(
188        profile_)->extension_service();
189
190    AddTestExtension(extension_service_, FPL("example1"));
191    AddTestExtension(extension_service_, FPL("example2"));
192
193    RegisterSyncableFileSystem();
194
195    fake_drive_service_ = new FakeDriveService;
196    DriveUploaderInterface* drive_uploader = new DriveUploader(
197        fake_drive_service_, base::MessageLoopProxy::current().get());
198
199    fake_drive_helper_.reset(new FakeDriveServiceHelper(
200        fake_drive_service_, drive_uploader,
201        APIUtil::GetSyncRootDirectoryName()));
202
203    api_util_ = APIUtil::CreateForTesting(
204        fake_drive_helper_->base_dir_path().AppendASCII("tmp"),
205        scoped_ptr<DriveServiceInterface>(fake_drive_service_),
206        scoped_ptr<DriveUploaderInterface>(drive_uploader)).Pass();
207    metadata_store_.reset(new DriveMetadataStore(
208        fake_drive_helper_->base_dir_path(),
209        base::MessageLoopProxy::current().get()));
210
211    bool done = false;
212    metadata_store_->Initialize(base::Bind(&DidInitialize, &done));
213    base::RunLoop().RunUntilIdle();
214    EXPECT_TRUE(done);
215
216    // Setup the sync root directory.
217    EXPECT_EQ(google_apis::HTTP_CREATED,
218              fake_drive_helper_->AddOrphanedFolder(
219                  APIUtil::GetSyncRootDirectoryName(),
220                  &sync_root_resource_id_));
221    metadata_store()->SetSyncRootDirectory(sync_root_resource_id_);
222  }
223
224  void SetUpDriveSyncService(bool enabled) {
225    sync_service_ = DriveFileSyncService::CreateForTesting(
226        profile_,
227        fake_drive_helper_->base_dir_path(),
228        api_util_.PassAs<APIUtilInterface>(),
229        metadata_store_.Pass()).Pass();
230    sync_service_->AddFileStatusObserver(&mock_file_status_observer_);
231    sync_service_->SetRemoteChangeProcessor(mock_remote_processor());
232    sync_service_->SetSyncEnabled(enabled);
233    base::RunLoop().RunUntilIdle();
234  }
235
236  virtual void TearDown() OVERRIDE {
237    if (sync_service_) {
238      sync_service_.reset();
239    }
240
241    metadata_store_.reset();
242    api_util_.reset();
243    fake_drive_service_ = NULL;
244
245    RevokeSyncableFileSystem();
246
247    extension_service_ = NULL;
248    profile_ = NULL;
249    profile_manager_.DeleteTestingProfile(kTestProfileName);
250    base::RunLoop().RunUntilIdle();
251  }
252
253 protected:
254  void EnableExtension(const std::string& extension_id) {
255    extension_service_->EnableExtension(extension_id);
256  }
257
258  void DisableExtension(const std::string& extension_id) {
259    extension_service_->DisableExtension(
260        extension_id, extensions::Extension::DISABLE_NONE);
261  }
262
263  void UninstallExtension(const std::string& extension_id) {
264    // Call UnloadExtension instead of UninstallExtension since it does
265    // unnecessary cleanup (e.g. deleting extension data) and emits warnings.
266    extension_service_->UnloadExtension(
267        extension_id, extensions::UnloadedExtensionInfo::REASON_UNINSTALL);
268  }
269
270  void UpdateRegisteredOrigins() {
271    sync_service_->UpdateRegisteredOrigins();
272    // Wait for completion of uninstalling origin.
273    base::RunLoop().RunUntilIdle();
274  }
275
276  void VerifySizeOfRegisteredOrigins(size_t b_size,
277                                     size_t i_size,
278                                     size_t d_size) {
279    EXPECT_EQ(b_size, pending_batch_sync_origins()->size());
280    EXPECT_EQ(i_size, metadata_store()->incremental_sync_origins().size());
281    EXPECT_EQ(d_size, metadata_store()->disabled_origins().size());
282  }
283
284  DriveMetadataStore* metadata_store() {
285    if (metadata_store_)
286      return metadata_store_.get();
287    return sync_service_->metadata_store_.get();
288  }
289
290  FakeDriveService* fake_drive_service() {
291    return fake_drive_service_;
292  }
293
294  StrictMock<MockFileStatusObserver>* mock_file_status_observer() {
295    return &mock_file_status_observer_;
296  }
297
298  StrictMock<MockRemoteChangeProcessor>* mock_remote_processor() {
299    return &mock_remote_processor_;
300  }
301
302  DriveFileSyncService* sync_service() { return sync_service_.get(); }
303  std::map<GURL, std::string>* pending_batch_sync_origins() {
304    return &(sync_service()->pending_batch_sync_origins_);
305  }
306
307  const RemoteChangeHandler& remote_change_handler() const {
308    return sync_service_->remote_change_handler_;
309  }
310
311  fileapi::FileSystemURL CreateURL(const GURL& origin,
312                                   const std::string& filename) {
313    return CreateSyncableFileSystemURL(
314        origin, base::FilePath::FromUTF8Unsafe(filename));
315  }
316
317  void ProcessRemoteChange(SyncStatusCode expected_status,
318                           const fileapi::FileSystemURL& expected_url,
319                           SyncFileStatus expected_sync_file_status,
320                           SyncAction expected_sync_action,
321                           SyncDirection expected_sync_direction) {
322    SyncStatusCode actual_status = SYNC_STATUS_UNKNOWN;
323    fileapi::FileSystemURL actual_url;
324
325    if (expected_sync_file_status != SYNC_FILE_STATUS_UNKNOWN) {
326      EXPECT_CALL(*mock_file_status_observer(),
327                  OnFileStatusChanged(expected_url,
328                                      expected_sync_file_status,
329                                      expected_sync_action,
330                                      expected_sync_direction))
331          .Times(1);
332    }
333
334    sync_service_->ProcessRemoteChange(
335        CreateResultReceiver(&actual_status, &actual_url));
336    base::RunLoop().RunUntilIdle();
337
338    EXPECT_EQ(expected_status, actual_status);
339    EXPECT_EQ(expected_url, actual_url);
340  }
341
342  bool AppendIncrementalRemoteChangeByResourceId(
343      const std::string& resource_id,
344      const GURL& origin) {
345    scoped_ptr<FileResource> entry;
346    EXPECT_EQ(google_apis::HTTP_SUCCESS,
347              fake_drive_helper_->GetFileResource(resource_id, &entry));
348    return sync_service_->AppendRemoteChange(
349        origin, *drive::util::ConvertFileResourceToResourceEntry(*entry),
350        12345);
351  }
352
353  bool AppendIncrementalRemoteChange(
354      const GURL& origin,
355      const base::FilePath& path,
356      bool is_deleted,
357      const std::string& resource_id,
358      int64 changestamp,
359      const std::string& remote_file_md5) {
360    return sync_service_->AppendRemoteChangeInternal(
361        origin, path, is_deleted, resource_id,
362        changestamp, remote_file_md5, base::Time(),
363        SYNC_FILE_TYPE_FILE);
364  }
365
366  std::string SetUpOriginRootDirectory(const char* extension_name) {
367    EXPECT_TRUE(!sync_root_resource_id_.empty());
368
369    std::string origin_root_resource_id;
370    EXPECT_EQ(google_apis::HTTP_CREATED,
371              fake_drive_helper_->AddFolder(
372                  sync_root_resource_id_,
373                  ExtensionNameToId(extension_name),
374                  &origin_root_resource_id));
375
376    metadata_store()->AddIncrementalSyncOrigin(
377        ExtensionNameToGURL(extension_name), origin_root_resource_id);
378    return origin_root_resource_id;
379  }
380
381  void AddNewFile(const GURL& origin,
382                  const std::string& parent_resource_id,
383                  const std::string& title,
384                  const std::string& content,
385                  scoped_ptr<google_apis::FileResource>* entry) {
386    std::string file_id;
387    ASSERT_EQ(google_apis::HTTP_SUCCESS,
388              fake_drive_helper_->AddFile(
389                  parent_resource_id, title, content, &file_id));
390    ASSERT_EQ(google_apis::HTTP_SUCCESS,
391              fake_drive_helper_->GetFileResource(
392                  file_id, entry));
393
394    DriveMetadata metadata;
395    metadata.set_resource_id(file_id);
396    metadata.set_md5_checksum((*entry)->md5_checksum());
397    metadata.set_conflicted(false);
398    metadata.set_to_be_fetched(false);
399    metadata.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
400
401    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
402    metadata_store()->UpdateEntry(
403        CreateURL(origin, title), metadata,
404        CreateResultReceiver(&status));
405    base::RunLoop().RunUntilIdle();
406    ASSERT_EQ(SYNC_STATUS_OK, status);
407  }
408
409  void TestRegisterNewOrigin();
410  void TestRegisterExistingOrigin();
411  void TestRegisterOriginWithSyncDisabled();
412  void TestUninstallOrigin();
413  void TestUpdateRegisteredOrigins();
414  void TestRemoteChange_NoChange();
415  void TestRemoteChange_Busy();
416  void TestRemoteChange_NewFile();
417  void TestRemoteChange_UpdateFile();
418  void TestRemoteChange_Override();
419  void TestRemoteChange_Folder();
420  void TestGetRemoteVersions();
421
422 private:
423  ScopedDisableSyncFSV2 scoped_disable_v2_;
424  content::TestBrowserThreadBundle thread_bundle_;
425
426  TestingProfileManager profile_manager_;
427  TestingProfile* profile_;
428
429  std::string sync_root_resource_id_;
430
431#if defined OS_CHROMEOS
432  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
433  chromeos::ScopedTestCrosSettings test_cros_settings_;
434  chromeos::ScopedTestUserManager test_user_manager_;
435#endif
436
437  scoped_ptr<DriveFileSyncService> sync_service_;
438
439  // Not owned.
440  ExtensionService* extension_service_;
441
442  FakeDriveService* fake_drive_service_;
443  scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
444
445  StrictMock<MockFileStatusObserver> mock_file_status_observer_;
446  StrictMock<MockRemoteChangeProcessor> mock_remote_processor_;
447
448  scoped_ptr<APIUtil> api_util_;
449  scoped_ptr<DriveMetadataStore> metadata_store_;
450
451  DISALLOW_COPY_AND_ASSIGN(DriveFileSyncServiceFakeTest);
452};
453
454#if !defined(OS_ANDROID)
455
456void DriveFileSyncServiceFakeTest::TestRegisterNewOrigin() {
457  SetUpDriveSyncService(true);
458  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
459  sync_service()->RegisterOrigin(
460      ExtensionNameToGURL(kExtensionName1),
461      CreateResultReceiver(&status));
462  base::RunLoop().RunUntilIdle();
463  EXPECT_EQ(SYNC_STATUS_OK, status);
464
465  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
466  EXPECT_TRUE(!remote_change_handler().HasChanges());
467}
468
469void DriveFileSyncServiceFakeTest::TestRegisterExistingOrigin() {
470  const std::string origin_resource_id =
471      SetUpOriginRootDirectory(kExtensionName1);
472
473  std::string file_id;
474  EXPECT_EQ(google_apis::HTTP_SUCCESS,
475            fake_drive_helper_->AddFile(
476                origin_resource_id, "1.txt", "data1", &file_id));
477  EXPECT_EQ(google_apis::HTTP_SUCCESS,
478            fake_drive_helper_->AddFile(
479                origin_resource_id, "2.txt", "data2", &file_id));
480  EXPECT_EQ(google_apis::HTTP_SUCCESS,
481            fake_drive_helper_->AddFile(
482                origin_resource_id, "3.txt", "data3", &file_id));
483
484  SetUpDriveSyncService(true);
485
486  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
487  sync_service()->RegisterOrigin(
488      ExtensionNameToGURL(kExtensionName1),
489      CreateResultReceiver(&status));
490  base::RunLoop().RunUntilIdle();
491  EXPECT_EQ(SYNC_STATUS_OK, status);
492
493  // The origin should be registered as an incremental sync origin.
494  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
495
496  // There are 3 items to sync.
497  EXPECT_EQ(3u, remote_change_handler().ChangesSize());
498}
499
500void DriveFileSyncServiceFakeTest::TestRegisterOriginWithSyncDisabled() {
501  // Usually the sync service starts here, but since we're setting up a drive
502  // service with sync disabled sync doesn't start (while register origin should
503  // still return OK).
504  SetUpDriveSyncService(false);
505
506  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
507  sync_service()->RegisterOrigin(
508      ExtensionNameToGURL(kExtensionName1),
509      CreateResultReceiver(&status));
510  base::RunLoop().RunUntilIdle();
511  EXPECT_EQ(SYNC_STATUS_OK, status);
512
513  // We must not have started batch sync for the newly registered origin,
514  // so it should still be in the batch_sync_origins.
515  VerifySizeOfRegisteredOrigins(1u, 0u, 0u);
516  EXPECT_TRUE(!remote_change_handler().HasChanges());
517}
518
519void DriveFileSyncServiceFakeTest::TestUninstallOrigin() {
520  SetUpOriginRootDirectory(kExtensionName1);
521  SetUpOriginRootDirectory(kExtensionName2);
522
523  SetUpDriveSyncService(true);
524
525  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
526  EXPECT_EQ(0u, remote_change_handler().ChangesSize());
527
528  SyncStatusCode status = SYNC_STATUS_UNKNOWN;
529  sync_service()->UninstallOrigin(
530      ExtensionNameToGURL(kExtensionName1),
531      RemoteFileSyncService::UNINSTALL_AND_PURGE_REMOTE,
532      CreateResultReceiver(&status));
533  base::RunLoop().RunUntilIdle();
534  EXPECT_EQ(SYNC_STATUS_OK, status);
535
536  VerifySizeOfRegisteredOrigins(0u, 1u, 0u);
537  EXPECT_TRUE(!remote_change_handler().HasChanges());
538}
539
540void DriveFileSyncServiceFakeTest::TestUpdateRegisteredOrigins() {
541  SetUpOriginRootDirectory(kExtensionName1);
542  SetUpOriginRootDirectory(kExtensionName2);
543  SetUpDriveSyncService(true);
544
545  // [1] Both extensions and origins are enabled. Nothing to do.
546  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
547  UpdateRegisteredOrigins();
548  VerifySizeOfRegisteredOrigins(0u, 2u, 0u);
549
550  // [2] Extension 1 should move to disabled list.
551  DisableExtension(ExtensionNameToId(kExtensionName1));
552  UpdateRegisteredOrigins();
553  VerifySizeOfRegisteredOrigins(0u, 1u, 1u);
554
555  // [3] Make sure that state remains the same, nothing should change.
556  UpdateRegisteredOrigins();
557  VerifySizeOfRegisteredOrigins(0u, 1u, 1u);
558
559  // [4] Uninstall Extension 2.
560  UninstallExtension(ExtensionNameToId(kExtensionName2));
561  UpdateRegisteredOrigins();
562  VerifySizeOfRegisteredOrigins(0u, 0u, 1u);
563
564  // [5] Re-enable Extension 1. It moves back to batch and not to incremental.
565  EnableExtension(ExtensionNameToId(kExtensionName1));
566  UpdateRegisteredOrigins();
567  VerifySizeOfRegisteredOrigins(1u, 0u, 0u);
568}
569
570void DriveFileSyncServiceFakeTest::TestRemoteChange_NoChange() {
571  SetUpDriveSyncService(true);
572
573  ProcessRemoteChange(SYNC_STATUS_NO_CHANGE_TO_SYNC,
574                      fileapi::FileSystemURL(),
575                      SYNC_FILE_STATUS_UNKNOWN,
576                      SYNC_ACTION_NONE,
577                      SYNC_DIRECTION_NONE);
578  VerifySizeOfRegisteredOrigins(0u, 0u, 0u);
579  EXPECT_TRUE(!remote_change_handler().HasChanges());
580}
581
582void DriveFileSyncServiceFakeTest::TestRemoteChange_Busy() {
583  const char kFileName[] = "File 1.txt";
584  const GURL origin = ExtensionNameToGURL(kExtensionName1);
585
586  const std::string origin_resource_id =
587      SetUpOriginRootDirectory(kExtensionName1);
588
589  EXPECT_CALL(*mock_remote_processor(),
590              PrepareForProcessRemoteChange(CreateURL(origin, kFileName), _))
591      .WillOnce(PrepareForRemoteChange_Busy());
592  EXPECT_CALL(*mock_remote_processor(),
593              FinalizeRemoteSync(CreateURL(origin, kFileName), _, _))
594      .WillOnce(InvokeCompletionCallback());
595
596  SetUpDriveSyncService(true);
597
598  std::string resource_id;
599  EXPECT_EQ(google_apis::HTTP_SUCCESS,
600            fake_drive_helper_->AddFile(
601                origin_resource_id, kFileName, "test data", &resource_id));
602  EXPECT_TRUE(AppendIncrementalRemoteChangeByResourceId(resource_id, origin));
603
604  ProcessRemoteChange(SYNC_STATUS_FILE_BUSY,
605                      CreateURL(origin, kFileName),
606                      SYNC_FILE_STATUS_UNKNOWN,
607                      SYNC_ACTION_NONE,
608                      SYNC_DIRECTION_NONE);
609}
610
611void DriveFileSyncServiceFakeTest::TestRemoteChange_NewFile() {
612  const char kFileName[] = "File 1.txt";
613  const GURL origin = ExtensionNameToGURL(kExtensionName1);
614
615  const std::string origin_resource_id =
616      SetUpOriginRootDirectory(kExtensionName1);
617
618  EXPECT_CALL(*mock_remote_processor(),
619              PrepareForProcessRemoteChange(CreateURL(origin, kFileName), _))
620      .WillOnce(PrepareForRemoteChange_NotFound());
621  EXPECT_CALL(*mock_remote_processor(),
622              FinalizeRemoteSync(CreateURL(origin, kFileName), _, _))
623      .WillOnce(InvokeCompletionCallback());
624
625  EXPECT_CALL(*mock_remote_processor(),
626              ApplyRemoteChange(_, _, CreateURL(origin, kFileName), _))
627      .WillOnce(InvokeDidApplyRemoteChange());
628
629  SetUpDriveSyncService(true);
630
631  std::string resource_id;
632  EXPECT_EQ(google_apis::HTTP_SUCCESS,
633            fake_drive_helper_->AddFile(
634                origin_resource_id, kFileName, "test data", &resource_id));
635  EXPECT_TRUE(AppendIncrementalRemoteChangeByResourceId(resource_id, origin));
636
637  ProcessRemoteChange(SYNC_STATUS_OK,
638                      CreateURL(origin, kFileName),
639                      SYNC_FILE_STATUS_SYNCED,
640                      SYNC_ACTION_ADDED,
641                      SYNC_DIRECTION_REMOTE_TO_LOCAL);
642}
643
644void DriveFileSyncServiceFakeTest::TestRemoteChange_UpdateFile() {
645  const char kFileName[] = "File 1.txt";
646  const GURL origin = ExtensionNameToGURL(kExtensionName1);
647
648  const std::string origin_resource_id =
649      SetUpOriginRootDirectory(kExtensionName1);
650
651  EXPECT_CALL(*mock_remote_processor(),
652              PrepareForProcessRemoteChange(CreateURL(origin, kFileName), _))
653      .WillOnce(PrepareForRemoteChange_NotModified());
654  EXPECT_CALL(*mock_remote_processor(),
655              FinalizeRemoteSync(CreateURL(origin, kFileName), _, _))
656      .WillOnce(InvokeCompletionCallback());
657
658  EXPECT_CALL(*mock_remote_processor(),
659              ApplyRemoteChange(_, _, CreateURL(origin, kFileName), _))
660      .WillOnce(InvokeDidApplyRemoteChange());
661
662  SetUpDriveSyncService(true);
663
664  std::string resource_id;
665  EXPECT_EQ(google_apis::HTTP_SUCCESS,
666            fake_drive_helper_->AddFile(
667                origin_resource_id, kFileName, "test data", &resource_id));
668  EXPECT_TRUE(AppendIncrementalRemoteChangeByResourceId(resource_id, origin));
669
670  ProcessRemoteChange(SYNC_STATUS_OK,
671                      CreateURL(origin, kFileName),
672                      SYNC_FILE_STATUS_SYNCED,
673                      SYNC_ACTION_UPDATED,
674                      SYNC_DIRECTION_REMOTE_TO_LOCAL);
675}
676
677void DriveFileSyncServiceFakeTest::TestRemoteChange_Override() {
678  const base::FilePath kFilePath(FPL("File 1.txt"));
679  const std::string kFileResourceId("file:2_file_resource_id");
680  const std::string kFileResourceId2("file:2_file_resource_id_2");
681  const GURL origin = ExtensionNameToGURL(kExtensionName1);
682
683  SetUpOriginRootDirectory(kExtensionName1);
684  SetUpDriveSyncService(true);
685
686  EXPECT_TRUE(AppendIncrementalRemoteChange(
687      origin, kFilePath, false /* is_deleted */,
688      kFileResourceId, 2, "remote_file_md5"));
689
690  // Expect to drop this change since there is another newer change on the
691  // queue.
692  EXPECT_FALSE(AppendIncrementalRemoteChange(
693      origin, kFilePath, false /* is_deleted */,
694      kFileResourceId, 1, "remote_file_md5_2"));
695
696  // Expect to drop this change since it has the same md5 with the previous one.
697  EXPECT_FALSE(AppendIncrementalRemoteChange(
698      origin, kFilePath, false /* is_deleted */,
699      kFileResourceId, 4, "remote_file_md5"));
700
701  // This should not cause browser crash.
702  EXPECT_FALSE(AppendIncrementalRemoteChange(
703      origin, kFilePath, false /* is_deleted */,
704      kFileResourceId, 4, "remote_file_md5"));
705
706  // Expect to drop these changes since they have different resource IDs with
707  // the previous ones.
708  EXPECT_FALSE(AppendIncrementalRemoteChange(
709      origin, kFilePath, false /* is_deleted */,
710      kFileResourceId2, 5, "updated_file_md5"));
711  EXPECT_FALSE(AppendIncrementalRemoteChange(
712      origin, kFilePath, true /* is_deleted */,
713      kFileResourceId2, 5, "deleted_file_md5"));
714
715  // Push delete change.
716  EXPECT_TRUE(AppendIncrementalRemoteChange(
717      origin, kFilePath, true /* is_deleted */,
718      kFileResourceId, 6, "deleted_file_md5"));
719
720  // Expect to drop this delete change since it has a different resource ID with
721  // the previous one.
722  EXPECT_FALSE(AppendIncrementalRemoteChange(
723      origin, kFilePath, true /* is_deleted */,
724      kFileResourceId2, 7, "deleted_file_md5"));
725
726  // Expect not to drop this change even if it has a different resource ID with
727  // the previous one.
728  EXPECT_TRUE(AppendIncrementalRemoteChange(
729      origin, kFilePath, false /* is_deleted */,
730      kFileResourceId2, 8, "updated_file_md5"));
731}
732
733void DriveFileSyncServiceFakeTest::TestRemoteChange_Folder() {
734  const std::string origin_resource_id =
735      SetUpOriginRootDirectory(kExtensionName1);
736  SetUpDriveSyncService(true);
737
738  std::string resource_id;
739  EXPECT_EQ(google_apis::HTTP_CREATED,
740            fake_drive_helper_->AddFolder(
741                origin_resource_id, "test_dir", &resource_id));
742
743  // Expect to drop this change for file.
744  EXPECT_FALSE(AppendIncrementalRemoteChangeByResourceId(
745      resource_id, ExtensionNameToGURL(kExtensionName1)));
746}
747
748TEST_F(DriveFileSyncServiceFakeTest, RegisterNewOrigin) {
749  ASSERT_FALSE(IsDriveAPIDisabled());
750  TestRegisterNewOrigin();
751}
752
753TEST_F(DriveFileSyncServiceFakeTest, RegisterNewOrigin_WAPI) {
754  ScopedDisableDriveAPI disable_drive_api;
755  TestRegisterNewOrigin();
756}
757
758TEST_F(DriveFileSyncServiceFakeTest, RegisterExistingOrigin) {
759  ASSERT_FALSE(IsDriveAPIDisabled());
760  TestRegisterExistingOrigin();
761}
762
763TEST_F(DriveFileSyncServiceFakeTest, RegisterExistingOrigin_WAPI) {
764  ScopedDisableDriveAPI disable_drive_api;
765  TestRegisterExistingOrigin();
766}
767
768TEST_F(DriveFileSyncServiceFakeTest, RegisterOriginWithSyncDisabled) {
769  ASSERT_FALSE(IsDriveAPIDisabled());
770  TestRegisterOriginWithSyncDisabled();
771}
772
773TEST_F(DriveFileSyncServiceFakeTest, RegisterOriginWithSyncDisabled_WAPI) {
774  ScopedDisableDriveAPI disable_drive_api;
775  TestRegisterOriginWithSyncDisabled();
776}
777
778TEST_F(DriveFileSyncServiceFakeTest, UninstallOrigin) {
779  ASSERT_FALSE(IsDriveAPIDisabled());
780  TestUninstallOrigin();
781}
782
783TEST_F(DriveFileSyncServiceFakeTest, UninstallOrigin_WAPI) {
784  ScopedDisableDriveAPI disable_drive_api;
785  TestUninstallOrigin();
786}
787
788TEST_F(DriveFileSyncServiceFakeTest, UpdateRegisteredOrigins) {
789  ASSERT_FALSE(IsDriveAPIDisabled());
790  TestUpdateRegisteredOrigins();
791}
792
793TEST_F(DriveFileSyncServiceFakeTest, UpdateRegisteredOrigins_WAPI) {
794  ScopedDisableDriveAPI disable_drive_api;
795  TestUpdateRegisteredOrigins();
796}
797
798TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NoChange) {
799  ASSERT_FALSE(IsDriveAPIDisabled());
800  TestRemoteChange_NoChange();
801}
802
803TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NoChange_WAPI) {
804  ScopedDisableDriveAPI disable_drive_api;
805  TestRemoteChange_NoChange();
806}
807
808TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Busy) {
809  ASSERT_FALSE(IsDriveAPIDisabled());
810  TestRemoteChange_Busy();
811}
812
813TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Busy_WAPI) {
814  ScopedDisableDriveAPI disable_drive_api;
815  TestRemoteChange_Busy();
816}
817
818TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NewFile) {
819  ASSERT_FALSE(IsDriveAPIDisabled());
820  TestRemoteChange_NewFile();
821}
822
823TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_NewFile_WAPI) {
824  ScopedDisableDriveAPI disable_drive_api;
825  TestRemoteChange_NewFile();
826}
827
828TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_UpdateFile) {
829  ASSERT_FALSE(IsDriveAPIDisabled());
830  TestRemoteChange_UpdateFile();
831}
832
833TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_UpdateFile_WAPI) {
834  ScopedDisableDriveAPI disable_drive_api;
835  TestRemoteChange_UpdateFile();
836}
837
838TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Override) {
839  ASSERT_FALSE(IsDriveAPIDisabled());
840  TestRemoteChange_Override();
841}
842
843TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Override_WAPI) {
844  ScopedDisableDriveAPI disable_drive_api;
845  TestRemoteChange_Override();
846}
847
848TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Folder) {
849  ASSERT_FALSE(IsDriveAPIDisabled());
850  TestRemoteChange_Folder();
851}
852
853TEST_F(DriveFileSyncServiceFakeTest, RemoteChange_Folder_WAPI) {
854  ScopedDisableDriveAPI disable_drive_api;
855  TestRemoteChange_Folder();
856}
857
858#endif  // !defined(OS_ANDROID)
859
860}  // namespace sync_file_system
861