root/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pending_local_changes_
  2. SetUp
  3. TearDown
  4. OnRemoteChangeQueueUpdated
  5. OnLocalChangeAvailable
  6. CreateURL
  7. CreateURL
  8. GetAppRootFolderID
  9. GetFileIDByPath
  10. GetFileIDByPath
  11. RegisterApp
  12. AddLocalFolder
  13. AddOrUpdateLocalFile
  14. UpdateLocalFile
  15. RemoveLocal
  16. ProcessLocalChange
  17. ProcessRemoteChange
  18. GetLargestChangeID
  19. FetchRemoteChanges
  20. ProcessChangesUntilDone
  21. VerifyConsistency
  22. VerifyConsistencyForFolder
  23. VerifyConsistencyForFile
  24. CountApp
  25. CountLocalFile
  26. VerifyLocalFile
  27. VerifyLocalFolder
  28. CountMetadata
  29. CountTracker
  30. fake_drive_service
  31. drive_uploader
  32. fake_drive_service_helper
  33. metadata_database
  34. TEST_F
  35. TEST_F
  36. TEST_F
  37. TEST_F
  38. TEST_F
  39. TEST_F
  40. TEST_F
  41. TEST_F
  42. TEST_F
  43. TEST_F
  44. TEST_F
  45. TEST_F
  46. TEST_F
  47. TEST_F
  48. TEST_F
  49. TEST_F
  50. TEST_F
  51. TEST_F
  52. TEST_F
  53. TEST_F
  54. TEST_F
  55. TEST_F
  56. TEST_F
  57. TEST_F
  58. TEST_F
  59. TEST_F
  60. TEST_F
  61. TEST_F
  62. TEST_F
  63. TEST_F
  64. TEST_F

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>
#include <stack>

#include "base/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "chrome/browser/drive/drive_uploader.h"
#include "chrome/browser/drive/fake_drive_service.h"
#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
#include "chrome/browser/sync_file_system/drive_backend/sync_engine.h"
#include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
#include "chrome/browser/sync_file_system/local/local_file_sync_context.h"
#include "chrome/browser/sync_file_system/local/local_file_sync_service.h"
#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h"
#include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "extensions/common/extension.h"
#include "google_apis/drive/drive_api_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
#include "third_party/leveldatabase/src/include/leveldb/env.h"
#include "webkit/browser/fileapi/file_system_context.h"

#define FPL(a) FILE_PATH_LITERAL(a)

namespace sync_file_system {
namespace drive_backend {

typedef fileapi::FileSystemOperation::FileEntryList FileEntryList;

class DriveBackendSyncTest : public testing::Test,
                             public LocalFileSyncService::Observer,
                             public RemoteFileSyncService::Observer {
 public:
  DriveBackendSyncTest()
      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
        pending_remote_changes_(0),
        pending_local_changes_(0) {}
  virtual ~DriveBackendSyncTest() {}

  virtual void SetUp() OVERRIDE {
    ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
    in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));

    io_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
        content::BrowserThread::IO);
    file_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
        content::BrowserThread::FILE);

    RegisterSyncableFileSystem();
    local_sync_service_ = LocalFileSyncService::CreateForTesting(
        &profile_, in_memory_env_.get());
    local_sync_service_->AddChangeObserver(this);

    scoped_ptr<drive::FakeDriveService> drive_service(
        new drive::FakeDriveService());
    drive_service->Initialize("test@example.com");
    ASSERT_TRUE(drive_service->LoadResourceListForWapi(
        "gdata/root_feed.json"));

    scoped_ptr<drive::DriveUploaderInterface> uploader(
        new drive::DriveUploader(drive_service.get(),
                                 file_task_runner_.get()));

    remote_sync_service_.reset(new SyncEngine(
        base_dir_.path(),
        file_task_runner_.get(),
        drive_service.PassAs<drive::DriveServiceInterface>(),
        uploader.Pass(),
        NULL, NULL, NULL, in_memory_env_.get()));
    remote_sync_service_->AddServiceObserver(this);
    remote_sync_service_->Initialize();
    remote_sync_service_->SetSyncEnabled(true);

    fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
        fake_drive_service(), drive_uploader(),
        kSyncRootFolderTitle));

    local_sync_service_->SetLocalChangeProcessor(remote_sync_service_.get());
    remote_sync_service_->SetRemoteChangeProcessor(local_sync_service_.get());
  }

  virtual void TearDown() OVERRIDE {
    typedef std::map<std::string, CannedSyncableFileSystem*>::iterator iterator;
    for (iterator itr = file_systems_.begin();
         itr != file_systems_.end(); ++itr) {
      itr->second->TearDown();
      delete itr->second;
    }
    file_systems_.clear();

    fake_drive_service_helper_.reset();
    remote_sync_service_.reset();

    base::RunLoop().RunUntilIdle();
    RevokeSyncableFileSystem();
  }

  virtual void OnRemoteChangeQueueUpdated(int64 pending_changes_hint) OVERRIDE {
    pending_remote_changes_ = pending_changes_hint;
  }

  virtual void OnLocalChangeAvailable(int64 pending_changes_hint) OVERRIDE {
    pending_local_changes_ = pending_changes_hint;
  }

 protected:
  fileapi::FileSystemURL CreateURL(const std::string& app_id,
                                   const base::FilePath::StringType& path) {
    return CreateURL(app_id, base::FilePath(path));
  }

  fileapi::FileSystemURL CreateURL(const std::string& app_id,
                                   const base::FilePath& path) {
    GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
    return CreateSyncableFileSystemURL(origin, path);
  }

  bool GetAppRootFolderID(const std::string& app_id,
                          std::string* folder_id) {
    FileTracker tracker;
    if (!metadata_database()->FindAppRootTracker(app_id, &tracker))
      return false;
    *folder_id = tracker.file_id();
    return true;
  }

  std::string GetFileIDByPath(const std::string& app_id,
                              const base::FilePath::StringType& path) {
    return GetFileIDByPath(app_id, base::FilePath(path));
  }

  std::string GetFileIDByPath(const std::string& app_id,
                              const base::FilePath& path) {
    FileTracker tracker;
    base::FilePath result_path;
    base::FilePath normalized_path = path.NormalizePathSeparators();
    EXPECT_TRUE(metadata_database()->FindNearestActiveAncestor(
        app_id, normalized_path, &tracker, &result_path));
    EXPECT_EQ(normalized_path, result_path);
    return tracker.file_id();
  }

  SyncStatusCode RegisterApp(const std::string& app_id) {
    GURL origin = extensions::Extension::GetBaseURLFromExtensionId(app_id);
    if (!ContainsKey(file_systems_, app_id)) {
      CannedSyncableFileSystem* file_system = new CannedSyncableFileSystem(
          origin, in_memory_env_.get(),
          io_task_runner_.get(), file_task_runner_.get());
      file_system->SetUp(CannedSyncableFileSystem::QUOTA_DISABLED);

      SyncStatusCode status = SYNC_STATUS_UNKNOWN;
      local_sync_service_->MaybeInitializeFileSystemContext(
          origin, file_system->file_system_context(),
          CreateResultReceiver(&status));
      base::RunLoop().RunUntilIdle();
      EXPECT_EQ(SYNC_STATUS_OK, status);

      file_system->backend()->sync_context()->
          set_mock_notify_changes_duration_in_sec(0);

      EXPECT_EQ(base::File::FILE_OK, file_system->OpenFileSystem());
      file_systems_[app_id] = file_system;
    }

    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    remote_sync_service_->RegisterOrigin(origin, CreateResultReceiver(&status));
    base::RunLoop().RunUntilIdle();
    return status;
  }

  void AddLocalFolder(const std::string& app_id,
                      const base::FilePath::StringType& path) {
    ASSERT_TRUE(ContainsKey(file_systems_, app_id));
    EXPECT_EQ(base::File::FILE_OK,
              file_systems_[app_id]->CreateDirectory(
                  CreateURL(app_id, path)));
  }

  void AddOrUpdateLocalFile(const std::string& app_id,
                            const base::FilePath::StringType& path,
                            const std::string& content) {
    fileapi::FileSystemURL url(CreateURL(app_id, path));
    ASSERT_TRUE(ContainsKey(file_systems_, app_id));
    EXPECT_EQ(base::File::FILE_OK, file_systems_[app_id]->CreateFile(url));
    int64 bytes_written = file_systems_[app_id]->WriteString(url, content);
    EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
    base::RunLoop().RunUntilIdle();
  }

  void UpdateLocalFile(const std::string& app_id,
                       const base::FilePath::StringType& path,
                       const std::string& content) {
    ASSERT_TRUE(ContainsKey(file_systems_, app_id));
    int64 bytes_written = file_systems_[app_id]->WriteString(
        CreateURL(app_id, path), content);
    EXPECT_EQ(static_cast<int64>(content.size()), bytes_written);
    base::RunLoop().RunUntilIdle();
  }

  void RemoveLocal(const std::string& app_id,
                   const base::FilePath::StringType& path) {
    ASSERT_TRUE(ContainsKey(file_systems_, app_id));
    EXPECT_EQ(base::File::FILE_OK,
              file_systems_[app_id]->Remove(
                  CreateURL(app_id, path),
                  true /* recursive */));
    base::RunLoop().RunUntilIdle();
  }

  SyncStatusCode ProcessLocalChange() {
    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    fileapi::FileSystemURL url;
    local_sync_service_->ProcessLocalChange(
        CreateResultReceiver(&status, &url));
    base::RunLoop().RunUntilIdle();
    return status;
  }

  SyncStatusCode ProcessRemoteChange() {
    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
    fileapi::FileSystemURL url;
    remote_sync_service_->ProcessRemoteChange(
        CreateResultReceiver(&status, &url));
    base::RunLoop().RunUntilIdle();
    return status;
  }

  int64 GetLargestChangeID() {
    scoped_ptr<google_apis::AboutResource> about_resource;
    EXPECT_EQ(google_apis::HTTP_SUCCESS,
              fake_drive_service_helper()->GetAboutResource(&about_resource));
    if (!about_resource)
      return 0;
    return about_resource->largest_change_id();
  }

  void FetchRemoteChanges() {
    remote_sync_service_->OnNotificationReceived();
    base::RunLoop().RunUntilIdle();
  }

  SyncStatusCode ProcessChangesUntilDone() {
    SyncStatusCode local_sync_status;
    SyncStatusCode remote_sync_status;
    while (true) {
      local_sync_status = ProcessLocalChange();
      if (local_sync_status != SYNC_STATUS_OK &&
          local_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC &&
          local_sync_status != SYNC_STATUS_FILE_BUSY)
        return local_sync_status;

      remote_sync_status = ProcessRemoteChange();
      if (remote_sync_status != SYNC_STATUS_OK &&
          remote_sync_status != SYNC_STATUS_NO_CHANGE_TO_SYNC &&
          remote_sync_status != SYNC_STATUS_FILE_BUSY)
        return remote_sync_status;

      if (local_sync_status == SYNC_STATUS_NO_CHANGE_TO_SYNC &&
          remote_sync_status == SYNC_STATUS_NO_CHANGE_TO_SYNC) {
        remote_sync_service_->PromoteDemotedChanges();
        local_sync_service_->PromoteDemotedChanges();

        if (pending_remote_changes_ || pending_local_changes_)
          continue;

        int64 largest_fetched_change_id =
            metadata_database()->GetLargestFetchedChangeID();
        if (largest_fetched_change_id != GetLargestChangeID()) {
          FetchRemoteChanges();
          continue;
        }
        break;
      }
    }
    return SYNC_STATUS_OK;
  }

  // Verifies local and remote files/folders are consistent.
  // This function checks:
  //  - Each registered origin has corresponding remote folder.
  //  - Each local file/folder has corresponding remote one.
  //  - Each remote file/folder has corresponding local one.
  // TODO(tzik): Handle conflict case. i.e. allow remote file has different
  // file content if the corresponding local file conflicts to it.
  void VerifyConsistency() {
    std::string sync_root_folder_id;
    google_apis::GDataErrorCode error =
        fake_drive_service_helper_->GetSyncRootFolderID(&sync_root_folder_id);
    if (sync_root_folder_id.empty()) {
      EXPECT_EQ(google_apis::HTTP_NOT_FOUND, error);
      EXPECT_TRUE(file_systems_.empty());
      return;
    }
    EXPECT_EQ(google_apis::HTTP_SUCCESS, error);

    ScopedVector<google_apis::ResourceEntry> remote_entries;
    EXPECT_EQ(google_apis::HTTP_SUCCESS,
              fake_drive_service_helper_->ListFilesInFolder(
                  sync_root_folder_id, &remote_entries));
    std::map<std::string, const google_apis::ResourceEntry*> app_root_by_title;
    for (ScopedVector<google_apis::ResourceEntry>::iterator itr =
             remote_entries.begin();
         itr != remote_entries.end();
         ++itr) {
      const google_apis::ResourceEntry& remote_entry = **itr;
      EXPECT_FALSE(ContainsKey(app_root_by_title, remote_entry.title()));
      app_root_by_title[remote_entry.title()] = *itr;
    }

    for (std::map<std::string, CannedSyncableFileSystem*>::const_iterator itr =
             file_systems_.begin();
         itr != file_systems_.end(); ++itr) {
      const std::string& app_id = itr->first;
      SCOPED_TRACE(testing::Message() << "Verifying app: " << app_id);
      CannedSyncableFileSystem* file_system = itr->second;
      ASSERT_TRUE(ContainsKey(app_root_by_title, app_id));
      VerifyConsistencyForFolder(
          app_id, base::FilePath(),
          app_root_by_title[app_id]->resource_id(),
          file_system);
    }
  }

  void VerifyConsistencyForFolder(const std::string& app_id,
                                  const base::FilePath& path,
                                  const std::string& folder_id,
                                  CannedSyncableFileSystem* file_system) {
    SCOPED_TRACE(testing::Message() << "Verifying folder: " << path.value());

    ScopedVector<google_apis::ResourceEntry> remote_entries;
    EXPECT_EQ(google_apis::HTTP_SUCCESS,
              fake_drive_service_helper_->ListFilesInFolder(
                  folder_id, &remote_entries));
    std::map<std::string, const google_apis::ResourceEntry*>
        remote_entry_by_title;
    for (size_t i = 0; i < remote_entries.size(); ++i) {
      google_apis::ResourceEntry* remote_entry = remote_entries[i];
      EXPECT_FALSE(ContainsKey(remote_entry_by_title, remote_entry->title()))
          << "title: " << remote_entry->title();
      remote_entry_by_title[remote_entry->title()] = remote_entry;
    }

    fileapi::FileSystemURL url(CreateURL(app_id, path));
    FileEntryList local_entries;
    EXPECT_EQ(base::File::FILE_OK,
              file_system->ReadDirectory(url, &local_entries));
    for (FileEntryList::iterator itr = local_entries.begin();
         itr != local_entries.end();
         ++itr) {
      const fileapi::DirectoryEntry& local_entry = *itr;
      fileapi::FileSystemURL entry_url(
          CreateURL(app_id, path.Append(local_entry.name)));
      std::string title =
          fileapi::VirtualPath::BaseName(entry_url.path()).AsUTF8Unsafe();
      SCOPED_TRACE(testing::Message() << "Verifying entry: " << title);

      ASSERT_TRUE(ContainsKey(remote_entry_by_title, title));
      const google_apis::ResourceEntry& remote_entry =
          *remote_entry_by_title[title];
      if (local_entry.is_directory) {
        ASSERT_TRUE(remote_entry.is_folder());
        VerifyConsistencyForFolder(app_id, entry_url.path(),
                                   remote_entry.resource_id(),
                                   file_system);
      } else {
        ASSERT_TRUE(remote_entry.is_file());
        VerifyConsistencyForFile(app_id, entry_url.path(),
                                 remote_entry.resource_id(),
                                 file_system);
      }
      remote_entry_by_title.erase(title);
    }

    EXPECT_TRUE(remote_entry_by_title.empty());
  }

  void VerifyConsistencyForFile(const std::string& app_id,
                                const base::FilePath& path,
                                const std::string& file_id,
                                CannedSyncableFileSystem* file_system) {
    fileapi::FileSystemURL url(CreateURL(app_id, path));
    std::string file_content;
    EXPECT_EQ(google_apis::HTTP_SUCCESS,
              fake_drive_service_helper_->ReadFile(file_id, &file_content));
    EXPECT_EQ(base::File::FILE_OK,
              file_system->VerifyFile(url, file_content));
  }

  size_t CountApp() {
    return file_systems_.size();
  }

  size_t CountLocalFile(const std::string& app_id) {
    if (!ContainsKey(file_systems_, app_id))
      return 0;

    CannedSyncableFileSystem* file_system = file_systems_[app_id];
    std::stack<base::FilePath> folders;
    folders.push(base::FilePath());  // root folder

    size_t result = 1;
    while (!folders.empty()) {
      fileapi::FileSystemURL url(CreateURL(app_id, folders.top()));
      folders.pop();

      FileEntryList entries;
      EXPECT_EQ(base::File::FILE_OK,
                file_system->ReadDirectory(url, &entries));
      for (FileEntryList::iterator itr = entries.begin();
           itr != entries.end(); ++itr) {
        ++result;
        if (itr->is_directory)
          folders.push(url.path().Append(itr->name));
      }
    }

    return result;
  }

  void VerifyLocalFile(const std::string& app_id,
                       const base::FilePath::StringType& path,
                       const std::string& content) {
    SCOPED_TRACE(testing::Message() << "Verifying local file: "
                                    << "app_id = " << app_id
                                    << ", path = " << path);
    ASSERT_TRUE(ContainsKey(file_systems_, app_id));
    EXPECT_EQ(base::File::FILE_OK,
              file_systems_[app_id]->VerifyFile(
                  CreateURL(app_id, path), content));
  }

  void VerifyLocalFolder(const std::string& app_id,
                         const base::FilePath::StringType& path) {
    SCOPED_TRACE(testing::Message() << "Verifying local file: "
                                    << "app_id = " << app_id
                                    << ", path = " << path);
    ASSERT_TRUE(ContainsKey(file_systems_, app_id));
    EXPECT_EQ(base::File::FILE_OK,
              file_systems_[app_id]->DirectoryExists(CreateURL(app_id, path)));
  }

  size_t CountMetadata() {
    return metadata_database()->CountFileMetadata();
  }

  size_t CountTracker() {
    return metadata_database()->CountFileTracker();
  }

  drive::FakeDriveService* fake_drive_service() {
    return static_cast<drive::FakeDriveService*>(
        remote_sync_service_->GetDriveService());
  }

  drive::DriveUploaderInterface* drive_uploader() {
    return remote_sync_service_->GetDriveUploader();
  }

  FakeDriveServiceHelper* fake_drive_service_helper() {
    return fake_drive_service_helper_.get();
  }

  MetadataDatabase* metadata_database() {
    return remote_sync_service_->GetMetadataDatabase();
  }

 private:
  content::TestBrowserThreadBundle thread_bundle_;
  ScopedEnableSyncFSV2 enable_syncfs_v2_;

  base::ScopedTempDir base_dir_;
  scoped_ptr<leveldb::Env> in_memory_env_;
  TestingProfile profile_;

  scoped_ptr<SyncEngine> remote_sync_service_;
  scoped_ptr<LocalFileSyncService> local_sync_service_;

  int64 pending_remote_changes_;
  int64 pending_local_changes_;

  scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
  std::map<std::string, CannedSyncableFileSystem*> file_systems_;


  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
  scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;

  DISALLOW_COPY_AND_ASSIGN(DriveBackendSyncTest);
};

TEST_F(DriveBackendSyncTest, LocalToRemoteBasicTest) {
  std::string app_id = "example";

  RegisterApp(app_id);
  AddOrUpdateLocalFile(app_id, FPL("file"), "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("file"), "abcde");

  EXPECT_EQ(3u, CountMetadata());
  EXPECT_EQ(3u, CountTracker());
}

TEST_F(DriveBackendSyncTest, RemoteToLocalBasicTest) {
  std::string app_id = "example";
  RegisterApp(app_id);

  std::string app_root_folder_id;
  EXPECT_TRUE(GetAppRootFolderID(app_id, &app_root_folder_id));

  std::string file_id;
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "file", "abcde", &file_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("file"), "abcde");

  EXPECT_EQ(3u, CountMetadata());
  EXPECT_EQ(3u, CountTracker());
}

TEST_F(DriveBackendSyncTest, LocalFileUpdateTest) {
  std::string app_id = "example";
  const base::FilePath::StringType kPath(FPL("file"));

  RegisterApp(app_id);
  AddOrUpdateLocalFile(app_id, kPath, "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  UpdateLocalFile(app_id, kPath, "1234567890");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("file"), "1234567890");

  EXPECT_EQ(3u, CountMetadata());
  EXPECT_EQ(3u, CountTracker());
}

TEST_F(DriveBackendSyncTest, RemoteFileUpdateTest) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string remote_file_id;
  std::string app_root_folder_id;
  EXPECT_TRUE(GetAppRootFolderID(app_id, &app_root_folder_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "file", "abcde", &remote_file_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateFile(
                remote_file_id, "1234567890"));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("file"), "1234567890");

  EXPECT_EQ(3u, CountMetadata());
  EXPECT_EQ(3u, CountTracker());
}

TEST_F(DriveBackendSyncTest, LocalFileDeletionTest) {
  std::string app_id = "example";
  const base::FilePath::StringType path(FPL("file"));

  RegisterApp(app_id);
  AddOrUpdateLocalFile(app_id, path, "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  RemoveLocal(app_id, path);

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(1u, CountLocalFile(app_id));

  EXPECT_EQ(2u, CountMetadata());
  EXPECT_EQ(2u, CountTracker());
}

TEST_F(DriveBackendSyncTest, RemoteFileDeletionTest) {
  std::string app_id = "example";
  const base::FilePath::StringType path(FPL("file"));

  RegisterApp(app_id);
  AddOrUpdateLocalFile(app_id, path, "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_id = GetFileIDByPath(app_id, path);
  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(file_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(1u, CountLocalFile(app_id));

  EXPECT_EQ(2u, CountMetadata());
  EXPECT_EQ(2u, CountTracker());
}

TEST_F(DriveBackendSyncTest, RemoteRenameTest) {
  std::string app_id = "example";
  const base::FilePath::StringType path(FPL("file"));

  RegisterApp(app_id);
  AddOrUpdateLocalFile(app_id, path, "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_id = GetFileIDByPath(app_id, path);
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->RenameResource(
                file_id, "renamed_file"));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("renamed_file"), "abcde");

  EXPECT_EQ(3u, CountMetadata());
  EXPECT_EQ(3u, CountTracker());
}

TEST_F(DriveBackendSyncTest, RemoteRenameAndRevertTest) {
  std::string app_id = "example";
  const base::FilePath::StringType path(FPL("file"));

  RegisterApp(app_id);
  AddOrUpdateLocalFile(app_id, path, "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_id = GetFileIDByPath(app_id, path);
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->RenameResource(
                file_id, "renamed_file"));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->RenameResource(
                file_id, base::FilePath(path).AsUTF8Unsafe()));

  FetchRemoteChanges();

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("file"), "abcde");

  EXPECT_EQ(3u, CountMetadata());
  EXPECT_EQ(3u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ReorganizeToOtherFolder) {
  std::string app_id = "example";
  const base::FilePath::StringType path(FPL("file"));

  RegisterApp(app_id);
  AddLocalFolder(app_id, FPL("folder_src"));
  AddLocalFolder(app_id, FPL("folder_dest"));
  AddOrUpdateLocalFile(app_id, FPL("folder_src/file"), "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_id = GetFileIDByPath(app_id, FPL("folder_src/file"));
  std::string src_folder_id = GetFileIDByPath(app_id, FPL("folder_src"));
  std::string dest_folder_id = GetFileIDByPath(app_id, FPL("folder_dest"));
  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->RemoveResourceFromDirectory(
                src_folder_id, file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddResourceToDirectory(
                dest_folder_id, file_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(4u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("folder_dest"));
  VerifyLocalFile(app_id, FPL("folder_dest/file"), "abcde");

  EXPECT_EQ(5u, CountMetadata());
  EXPECT_EQ(5u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ReorganizeToOtherApp) {
  std::string src_app_id = "src_app";
  std::string dest_app_id = "dest_app";

  RegisterApp(src_app_id);
  RegisterApp(dest_app_id);

  AddLocalFolder(src_app_id, FPL("folder_src"));
  AddLocalFolder(dest_app_id, FPL("folder_dest"));
  AddOrUpdateLocalFile(src_app_id, FPL("folder_src/file"), "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_id = GetFileIDByPath(src_app_id, FPL("folder_src/file"));
  std::string src_folder_id = GetFileIDByPath(src_app_id, FPL("folder_src"));
  std::string dest_folder_id = GetFileIDByPath(dest_app_id, FPL("folder_dest"));
  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->RemoveResourceFromDirectory(
                src_folder_id, file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddResourceToDirectory(
                dest_folder_id, file_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(2u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(src_app_id));
  EXPECT_EQ(3u, CountLocalFile(dest_app_id));
  VerifyLocalFile(dest_app_id, FPL("folder_dest/file"), "abcde");

  EXPECT_EQ(6u, CountMetadata());
  EXPECT_EQ(6u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ReorganizeToUnmanagedArea) {
  std::string app_id = "example";

  RegisterApp(app_id);

  AddLocalFolder(app_id, FPL("folder_src"));
  AddOrUpdateLocalFile(app_id, FPL("folder_src/file_orphaned"), "abcde");
  AddOrUpdateLocalFile(app_id, FPL("folder_src/file_under_sync_root"), "123");
  AddOrUpdateLocalFile(app_id, FPL("folder_src/file_under_drive_root"), "hoge");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_orphaned_id =
      GetFileIDByPath(app_id, FPL("folder_src/file_orphaned"));
  std::string file_under_sync_root_id =
      GetFileIDByPath(app_id, FPL("folder_src/file_under_sync_root"));
  std::string file_under_drive_root_id =
      GetFileIDByPath(app_id, FPL("folder_src/file_under_drive_root"));

  std::string folder_id = GetFileIDByPath(app_id, FPL("folder_src"));
  std::string sync_root_folder_id;
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->GetSyncRootFolderID(
                &sync_root_folder_id));

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->RemoveResourceFromDirectory(
                folder_id, file_orphaned_id));
  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->RemoveResourceFromDirectory(
                folder_id, file_under_sync_root_id));
  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->RemoveResourceFromDirectory(
                folder_id, file_under_drive_root_id));

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddResourceToDirectory(
                sync_root_folder_id, file_under_sync_root_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddResourceToDirectory(
                fake_drive_service()->GetRootResourceId(),
                file_under_drive_root_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ReorganizeToMultipleParents) {
  std::string app_id = "example";

  RegisterApp(app_id);

  AddLocalFolder(app_id, FPL("parent1"));
  AddLocalFolder(app_id, FPL("parent2"));
  AddOrUpdateLocalFile(app_id, FPL("parent1/file"), "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_id = GetFileIDByPath(app_id, FPL("parent1/file"));
  std::string parent2_folder_id = GetFileIDByPath(app_id, FPL("parent2"));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddResourceToDirectory(
                parent2_folder_id, file_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(4u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("parent1"));
  VerifyLocalFolder(app_id, FPL("parent2"));
  VerifyLocalFile(app_id, FPL("parent1/file"), "abcde");

  EXPECT_EQ(5u, CountMetadata());
  EXPECT_EQ(5u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ReorganizeAndRevert) {
  std::string app_id = "example";

  RegisterApp(app_id);

  AddLocalFolder(app_id, FPL("folder"));
  AddLocalFolder(app_id, FPL("folder_temp"));
  AddOrUpdateLocalFile(app_id, FPL("folder/file"), "abcde");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  std::string file_id = GetFileIDByPath(app_id, FPL("folder/file"));
  std::string folder_id = GetFileIDByPath(app_id, FPL("folder"));
  std::string folder_temp_id = GetFileIDByPath(app_id, FPL("folder_temp"));
  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->RemoveResourceFromDirectory(
                folder_id, file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddResourceToDirectory(
                folder_temp_id, file_id));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->RemoveResourceFromDirectory(
                folder_temp_id, file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddResourceToDirectory(
                folder_id, file_id));

  FetchRemoteChanges();

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(4u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("folder"));
  VerifyLocalFile(app_id, FPL("folder/file"), "abcde");

  EXPECT_EQ(5u, CountMetadata());
  EXPECT_EQ(5u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFolder_AddFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));

  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  std::string remote_folder_id;
  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id,
                "conflict_to_pending_remote", &remote_folder_id));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id,
                "conflict_to_existing_remote", &remote_folder_id));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  VerifyLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFolder_DeleteFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);

  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(2u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("conflict_to_pending_remote"));

  EXPECT_EQ(3u, CountMetadata());
  EXPECT_EQ(3u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFolder_AddFile) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));

  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  std::string file_id;
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_pending_remote", "foo",
                &file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateModificationTime(
                file_id,
                base::Time::Now() + base::TimeDelta::FromDays(1)));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_existing_remote", "foo",
                &file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateModificationTime(
                file_id,
                base::Time::Now() + base::TimeDelta::FromDays(1)));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  VerifyLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFolder_DeleteFile) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));

  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));

  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  VerifyLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFolder_AddFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));
  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  std::string file_id;
  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id,
                "conflict_to_pending_remote", &file_id));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id,
                "conflict_to_existing_remote", NULL));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  VerifyLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFolder_DeleteFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));

  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(1u, CountLocalFile(app_id));

  EXPECT_EQ(2u, CountMetadata());
  EXPECT_EQ(2u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFolder_AddFile) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));

  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_pending_remote", "foo", NULL));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_existing_remote", "bar",
                NULL));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  VerifyLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFolder_DeleteFile) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(1u, CountLocalFile(app_id));

  EXPECT_EQ(2u, CountMetadata());
  EXPECT_EQ(2u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFile_AddFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));

  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  std::string file_id;
  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id, "conflict_to_pending_remote",
                &file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateModificationTime(
                file_id,
                base::Time::Now() - base::TimeDelta::FromDays(1)));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id, "conflict_to_existing_remote",
                &file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateModificationTime(
                file_id,
                base::Time::Now() - base::TimeDelta::FromDays(1)));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  VerifyLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFile_DeleteFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);
  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));

  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  VerifyLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFile_AddFile) {
  std::string app_id = "example";

  RegisterApp(app_id);

  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "hoge");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "fuga");

  std::string file_id;
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_pending_remote", "foo",
                &file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateModificationTime(
                file_id,
                base::Time::Now() + base::TimeDelta::FromDays(1)));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_existing_remote", "bar",
                &file_id));
  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateModificationTime(
                file_id,
                base::Time::Now() + base::TimeDelta::FromDays(1)));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  VerifyLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_AddFile_DeleteFile) {
  std::string app_id = "example";

  RegisterApp(app_id);

  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "hoge");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "fuga");

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("conflict_to_pending_remote"), "hoge");
  VerifyLocalFile(app_id, FPL("conflict_to_existing_remote"), "fuga");

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_UpdateFile_DeleteFile) {
  std::string app_id = "example";

  RegisterApp(app_id);

  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "hoge");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "fuga");

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("conflict_to_pending_remote"), "hoge");
  VerifyLocalFile(app_id, FPL("conflict_to_existing_remote"), "fuga");

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFile_AddFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);

  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id, "conflict_to_pending_remote", NULL));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_CREATED,
            fake_drive_service_helper()->AddFolder(
                app_root_folder_id, "conflict_to_existing_remote", NULL));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  VerifyLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFile_DeleteFolder) {
  std::string app_id = "example";

  RegisterApp(app_id);

  AddLocalFolder(app_id, FPL("conflict_to_pending_remote"));
  AddLocalFolder(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(1u, CountLocalFile(app_id));

  EXPECT_EQ(2u, CountMetadata());
  EXPECT_EQ(2u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFile_AddFile) {
  std::string app_id = "example";

  RegisterApp(app_id);

  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_pending_remote", "hoge",
                NULL));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->AddFile(
                app_root_folder_id, "conflict_to_existing_remote", "fuga",
                NULL));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("conflict_to_pending_remote"), "hoge");
  VerifyLocalFile(app_id, FPL("conflict_to_existing_remote"), "fuga");

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFile_UpdateFile) {
  std::string app_id = "example";

  RegisterApp(app_id);

  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateFile(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote")),
                "hoge"));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_SUCCESS,
            fake_drive_service_helper()->UpdateFile(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote")),
                "fuga"));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(3u, CountLocalFile(app_id));
  VerifyLocalFile(app_id, FPL("conflict_to_pending_remote"), "hoge");
  VerifyLocalFile(app_id, FPL("conflict_to_existing_remote"), "fuga");

  EXPECT_EQ(4u, CountMetadata());
  EXPECT_EQ(4u, CountTracker());
}

TEST_F(DriveBackendSyncTest, ConflictTest_DeleteFile_DeleteFile) {
  std::string app_id = "example";

  RegisterApp(app_id);

  std::string app_root_folder_id = GetFileIDByPath(app_id, FPL(""));
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_pending_remote"), "foo");
  AddOrUpdateLocalFile(app_id, FPL("conflict_to_existing_remote"), "bar");

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  // Test body starts from here.
  RemoveLocal(app_id, FPL("conflict_to_pending_remote"));
  RemoveLocal(app_id, FPL("conflict_to_existing_remote"));

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_pending_remote"))));

  FetchRemoteChanges();

  EXPECT_EQ(google_apis::HTTP_NO_CONTENT,
            fake_drive_service_helper()->DeleteResource(
                GetFileIDByPath(app_id, FPL("conflict_to_existing_remote"))));

  EXPECT_EQ(SYNC_STATUS_OK, ProcessChangesUntilDone());
  VerifyConsistency();

  EXPECT_EQ(1u, CountApp());
  EXPECT_EQ(1u, CountLocalFile(app_id));

  EXPECT_EQ(2u, CountMetadata());
  EXPECT_EQ(2u, CountTracker());
}

}  // namespace drive_backend
}  // namespace sync_file_system

/* [<][>][^][v][top][bottom][index][help] */