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