Home | History | Annotate | Download | only in file_system
      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/chromeos/drive/file_system/copy_operation.h"
      6 
      7 #include "base/files/file_util.h"
      8 #include "base/task_runner_util.h"
      9 #include "chrome/browser/chromeos/drive/file_cache.h"
     10 #include "chrome/browser/chromeos/drive/file_change.h"
     11 #include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
     12 #include "chrome/browser/chromeos/drive/file_system_util.h"
     13 #include "chrome/browser/chromeos/drive/resource_metadata.h"
     14 #include "chrome/browser/drive/drive_api_util.h"
     15 #include "chrome/browser/drive/fake_drive_service.h"
     16 #include "content/public/test/test_utils.h"
     17 #include "google_apis/drive/drive_api_parser.h"
     18 #include "google_apis/drive/test_util.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 namespace drive {
     22 namespace file_system {
     23 
     24 namespace {
     25 
     26 // Used to handle WaitForSyncComplete() calls.
     27 bool CopyWaitForSyncCompleteArguments(std::string* out_local_id,
     28                                       FileOperationCallback* out_callback,
     29                                       const std::string& local_id,
     30                                       const FileOperationCallback& callback) {
     31   *out_local_id = local_id;
     32   *out_callback = callback;
     33   return true;
     34 }
     35 
     36 }  // namespace
     37 
     38 class CopyOperationTest : public OperationTestBase {
     39  protected:
     40   virtual void SetUp() OVERRIDE {
     41    OperationTestBase::SetUp();
     42    operation_.reset(new CopyOperation(
     43        blocking_task_runner(), delegate(), scheduler(), metadata(), cache()));
     44   }
     45 
     46   scoped_ptr<CopyOperation> operation_;
     47 };
     48 
     49 TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_RegularFile) {
     50   const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
     51   const base::FilePath remote_dest_path(
     52       FILE_PATH_LITERAL("drive/root/remote.txt"));
     53 
     54   // Prepare a local file.
     55   ASSERT_TRUE(
     56       google_apis::test_util::WriteStringToFile(local_src_path, "hello"));
     57   // Confirm that the remote file does not exist.
     58   ResourceEntry entry;
     59   ASSERT_EQ(FILE_ERROR_NOT_FOUND,
     60             GetLocalResourceEntry(remote_dest_path, &entry));
     61 
     62   // Transfer the local file to Drive.
     63   FileError error = FILE_ERROR_FAILED;
     64   operation_->TransferFileFromLocalToRemote(
     65       local_src_path,
     66       remote_dest_path,
     67       google_apis::test_util::CreateCopyResultCallback(&error));
     68   content::RunAllBlockingPoolTasksUntilIdle();
     69   EXPECT_EQ(FILE_ERROR_OK, error);
     70 
     71   // TransferFileFromLocalToRemote stores a copy of the local file in the cache,
     72   // marks it dirty and requests the observer to upload the file.
     73   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
     74   EXPECT_EQ(1U, delegate()->updated_local_ids().count(entry.local_id()));
     75   EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
     76   EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
     77 
     78   EXPECT_EQ(1U, delegate()->get_changed_files().size());
     79   EXPECT_TRUE(delegate()->get_changed_files().count(remote_dest_path));
     80 }
     81 
     82 TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_Overwrite) {
     83   const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
     84   const base::FilePath remote_dest_path(
     85       FILE_PATH_LITERAL("drive/root/File 1.txt"));
     86 
     87   // Prepare a local file.
     88   EXPECT_TRUE(
     89       google_apis::test_util::WriteStringToFile(local_src_path, "hello"));
     90   // Confirm that the remote file exists.
     91   ResourceEntry entry;
     92   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
     93 
     94   // Transfer the local file to Drive.
     95   FileError error = FILE_ERROR_FAILED;
     96   operation_->TransferFileFromLocalToRemote(
     97       local_src_path,
     98       remote_dest_path,
     99       google_apis::test_util::CreateCopyResultCallback(&error));
    100   content::RunAllBlockingPoolTasksUntilIdle();
    101   EXPECT_EQ(FILE_ERROR_OK, error);
    102 
    103   // TransferFileFromLocalToRemote stores a copy of the local file in the cache,
    104   // marks it dirty and requests the observer to upload the file.
    105   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
    106   EXPECT_EQ(1U, delegate()->updated_local_ids().count(entry.local_id()));
    107   EXPECT_TRUE(entry.file_specific_info().cache_state().is_present());
    108   EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
    109 
    110   EXPECT_EQ(1U, delegate()->get_changed_files().size());
    111   EXPECT_TRUE(delegate()->get_changed_files().count(remote_dest_path));
    112 }
    113 
    114 TEST_F(CopyOperationTest,
    115        TransferFileFromLocalToRemote_ExistingHostedDocument) {
    116   const base::FilePath local_src_path = temp_dir().AppendASCII("local.gdoc");
    117   const base::FilePath remote_dest_path(FILE_PATH_LITERAL(
    118       "drive/root/Directory 1/copied.gdoc"));
    119 
    120   // Prepare a local file, which is a json file of a hosted document, which
    121   // matches "drive/root/Document 1 excludeDir-test".
    122   ASSERT_TRUE(util::CreateGDocFile(
    123       local_src_path,
    124       GURL("https://3_document_self_link/5_document_resource_id"),
    125       "5_document_resource_id"));
    126 
    127   ResourceEntry entry;
    128   ASSERT_EQ(FILE_ERROR_NOT_FOUND,
    129             GetLocalResourceEntry(remote_dest_path, &entry));
    130 
    131   // Transfer the local file to Drive.
    132   FileError error = FILE_ERROR_FAILED;
    133   operation_->TransferFileFromLocalToRemote(
    134       local_src_path,
    135       remote_dest_path,
    136       google_apis::test_util::CreateCopyResultCallback(&error));
    137   content::RunAllBlockingPoolTasksUntilIdle();
    138   EXPECT_EQ(FILE_ERROR_OK, error);
    139 
    140   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
    141 
    142   EXPECT_EQ(1U, delegate()->get_changed_files().size());
    143   EXPECT_TRUE(delegate()->get_changed_files().count(remote_dest_path));
    144   // New copy is created.
    145   EXPECT_NE("5_document_resource_id", entry.resource_id());
    146 }
    147 
    148 TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_OrphanHostedDocument) {
    149   const base::FilePath local_src_path = temp_dir().AppendASCII("local.gdoc");
    150   const base::FilePath remote_dest_path(FILE_PATH_LITERAL(
    151       "drive/root/Directory 1/moved.gdoc"));
    152 
    153   // Prepare a local file, which is a json file of a hosted document, which
    154   // matches "drive/other/Orphan Document".
    155   ASSERT_TRUE(util::CreateGDocFile(
    156       local_src_path,
    157       GURL("https://3_document_self_link/orphan_doc_1"),
    158       "orphan_doc_1"));
    159 
    160   ResourceEntry entry;
    161   ASSERT_EQ(FILE_ERROR_NOT_FOUND,
    162             GetLocalResourceEntry(remote_dest_path, &entry));
    163 
    164   // Transfer the local file to Drive.
    165   FileError error = FILE_ERROR_FAILED;
    166   operation_->TransferFileFromLocalToRemote(
    167       local_src_path,
    168       remote_dest_path,
    169       google_apis::test_util::CreateCopyResultCallback(&error));
    170   content::RunAllBlockingPoolTasksUntilIdle();
    171   EXPECT_EQ(FILE_ERROR_OK, error);
    172 
    173   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
    174   EXPECT_EQ(ResourceEntry::DIRTY, entry.metadata_edit_state());
    175   EXPECT_TRUE(delegate()->updated_local_ids().count(entry.local_id()));
    176 
    177   EXPECT_EQ(1U, delegate()->get_changed_files().size());
    178   EXPECT_TRUE(delegate()->get_changed_files().count(remote_dest_path));
    179   // The original document got new parent.
    180   EXPECT_EQ("orphan_doc_1", entry.resource_id());
    181 }
    182 
    183 TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_NewHostedDocument) {
    184   const base::FilePath local_src_path = temp_dir().AppendASCII("local.gdoc");
    185   const base::FilePath remote_dest_path(FILE_PATH_LITERAL(
    186       "drive/root/Directory 1/moved.gdoc"));
    187 
    188   // Create a hosted document on the server that is not synced to local yet.
    189   google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
    190   scoped_ptr<google_apis::FileResource> new_gdoc_entry;
    191   fake_service()->AddNewFile(
    192       "application/vnd.google-apps.document", "", "", "title", true,
    193       google_apis::test_util::CreateCopyResultCallback(&gdata_error,
    194                                                        &new_gdoc_entry));
    195   content::RunAllBlockingPoolTasksUntilIdle();
    196   ASSERT_EQ(google_apis::HTTP_CREATED, gdata_error);
    197 
    198   // Prepare a local file, which is a json file of the added hosted document.
    199   ASSERT_TRUE(util::CreateGDocFile(
    200       local_src_path,
    201       GURL("https://3_document_self_link/" + new_gdoc_entry->file_id()),
    202       new_gdoc_entry->file_id()));
    203 
    204   ResourceEntry entry;
    205   ASSERT_EQ(FILE_ERROR_NOT_FOUND,
    206             GetLocalResourceEntry(remote_dest_path, &entry));
    207 
    208   // Transfer the local file to Drive.
    209   FileError error = FILE_ERROR_FAILED;
    210   operation_->TransferFileFromLocalToRemote(
    211       local_src_path,
    212       remote_dest_path,
    213       google_apis::test_util::CreateCopyResultCallback(&error));
    214   content::RunAllBlockingPoolTasksUntilIdle();
    215   EXPECT_EQ(FILE_ERROR_OK, error);
    216 
    217   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(remote_dest_path, &entry));
    218 
    219   EXPECT_EQ(1U, delegate()->get_changed_files().size());
    220   EXPECT_TRUE(delegate()->get_changed_files().count(remote_dest_path));
    221   // The original document got new parent.
    222   EXPECT_EQ(new_gdoc_entry->file_id(), entry.resource_id());
    223 }
    224 
    225 TEST_F(CopyOperationTest, CopyNotExistingFile) {
    226   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/Dummy file.txt"));
    227   base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Test.log"));
    228 
    229   ResourceEntry entry;
    230   ASSERT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(src_path, &entry));
    231 
    232   FileError error = FILE_ERROR_OK;
    233   operation_->Copy(src_path,
    234                    dest_path,
    235                    false,
    236                    google_apis::test_util::CreateCopyResultCallback(&error));
    237   content::RunAllBlockingPoolTasksUntilIdle();
    238   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    239 
    240   EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(src_path, &entry));
    241   EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
    242   EXPECT_TRUE(delegate()->get_changed_files().empty());
    243 }
    244 
    245 TEST_F(CopyOperationTest, CopyFileToNonExistingDirectory) {
    246   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
    247   base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Dummy/Test.log"));
    248 
    249   ResourceEntry entry;
    250   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
    251   ASSERT_EQ(FILE_ERROR_NOT_FOUND,
    252             GetLocalResourceEntry(dest_path.DirName(), &entry));
    253 
    254   FileError error = FILE_ERROR_OK;
    255   operation_->Copy(src_path,
    256                    dest_path,
    257                    false,
    258                    google_apis::test_util::CreateCopyResultCallback(&error));
    259   content::RunAllBlockingPoolTasksUntilIdle();
    260   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    261 
    262   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
    263   EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
    264   EXPECT_TRUE(delegate()->get_changed_files().empty());
    265 }
    266 
    267 // Test the case where the parent of the destination path is an existing file,
    268 // not a directory.
    269 TEST_F(CopyOperationTest, CopyFileToInvalidPath) {
    270   base::FilePath src_path(FILE_PATH_LITERAL(
    271       "drive/root/Document 1 excludeDir-test.gdoc"));
    272   base::FilePath dest_path(FILE_PATH_LITERAL(
    273       "drive/root/Duplicate Name.txt/Document 1 excludeDir-test.gdoc"));
    274 
    275   ResourceEntry entry;
    276   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
    277   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path.DirName(), &entry));
    278   ASSERT_FALSE(entry.file_info().is_directory());
    279 
    280   FileError error = FILE_ERROR_OK;
    281   operation_->Copy(src_path,
    282                    dest_path,
    283                    false,
    284                    google_apis::test_util::CreateCopyResultCallback(&error));
    285   content::RunAllBlockingPoolTasksUntilIdle();
    286   EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
    287 
    288   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
    289   EXPECT_EQ(FILE_ERROR_NOT_FOUND, GetLocalResourceEntry(dest_path, &entry));
    290   EXPECT_TRUE(delegate()->get_changed_files().empty());
    291 }
    292 
    293 TEST_F(CopyOperationTest, CopyDirtyFile) {
    294   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
    295   base::FilePath dest_path(FILE_PATH_LITERAL(
    296       "drive/root/Directory 1/New File.txt"));
    297 
    298   ResourceEntry src_entry;
    299   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
    300 
    301   // Store a dirty cache file.
    302   base::FilePath temp_file;
    303   EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir(), &temp_file));
    304   std::string contents = "test content";
    305   EXPECT_TRUE(google_apis::test_util::WriteStringToFile(temp_file, contents));
    306   FileError error = FILE_ERROR_FAILED;
    307   base::PostTaskAndReplyWithResult(
    308       blocking_task_runner(),
    309       FROM_HERE,
    310       base::Bind(&internal::FileCache::Store,
    311                  base::Unretained(cache()),
    312                  src_entry.local_id(),
    313                  std::string(),
    314                  temp_file,
    315                  internal::FileCache::FILE_OPERATION_MOVE),
    316       google_apis::test_util::CreateCopyResultCallback(&error));
    317   content::RunAllBlockingPoolTasksUntilIdle();
    318   EXPECT_EQ(FILE_ERROR_OK, error);
    319 
    320   // Copy.
    321   operation_->Copy(src_path,
    322                    dest_path,
    323                    false,
    324                    google_apis::test_util::CreateCopyResultCallback(&error));
    325   content::RunAllBlockingPoolTasksUntilIdle();
    326   EXPECT_EQ(FILE_ERROR_OK, error);
    327 
    328   ResourceEntry dest_entry;
    329   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &dest_entry));
    330   EXPECT_EQ(ResourceEntry::DIRTY, dest_entry.metadata_edit_state());
    331 
    332   EXPECT_EQ(1u, delegate()->updated_local_ids().size());
    333   EXPECT_TRUE(delegate()->updated_local_ids().count(dest_entry.local_id()));
    334   EXPECT_EQ(1u, delegate()->get_changed_files().size());
    335   EXPECT_TRUE(delegate()->get_changed_files().count(dest_path));
    336 
    337   // Copied cache file should be dirty.
    338   EXPECT_TRUE(dest_entry.file_specific_info().cache_state().is_dirty());
    339 
    340   // File contents should match.
    341   base::FilePath cache_file_path;
    342   base::PostTaskAndReplyWithResult(
    343       blocking_task_runner(),
    344       FROM_HERE,
    345       base::Bind(&internal::FileCache::GetFile,
    346                  base::Unretained(cache()),
    347                  dest_entry.local_id(),
    348                  &cache_file_path),
    349       google_apis::test_util::CreateCopyResultCallback(&error));
    350   content::RunAllBlockingPoolTasksUntilIdle();
    351   EXPECT_EQ(FILE_ERROR_OK, error);
    352 
    353   std::string copied_contents;
    354   EXPECT_TRUE(base::ReadFileToString(cache_file_path, &copied_contents));
    355   EXPECT_EQ(contents, copied_contents);
    356 }
    357 
    358 TEST_F(CopyOperationTest, CopyFileOverwriteFile) {
    359   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
    360   base::FilePath dest_path(FILE_PATH_LITERAL(
    361       "drive/root/Directory 1/SubDirectory File 1.txt"));
    362 
    363   ResourceEntry old_dest_entry;
    364   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &old_dest_entry));
    365 
    366   FileError error = FILE_ERROR_OK;
    367   operation_->Copy(src_path,
    368                    dest_path,
    369                    false,
    370                    google_apis::test_util::CreateCopyResultCallback(&error));
    371   content::RunAllBlockingPoolTasksUntilIdle();
    372   EXPECT_EQ(FILE_ERROR_OK, error);
    373 
    374   ResourceEntry new_dest_entry;
    375   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &new_dest_entry));
    376 
    377   EXPECT_EQ(1u, delegate()->updated_local_ids().size());
    378   EXPECT_TRUE(delegate()->updated_local_ids().count(old_dest_entry.local_id()));
    379   EXPECT_EQ(1u, delegate()->get_changed_files().size());
    380   EXPECT_TRUE(delegate()->get_changed_files().count(dest_path));
    381 }
    382 
    383 TEST_F(CopyOperationTest, CopyFileOverwriteDirectory) {
    384   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
    385   base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/Directory 1"));
    386 
    387   FileError error = FILE_ERROR_OK;
    388   operation_->Copy(src_path,
    389                    dest_path,
    390                    false,
    391                    google_apis::test_util::CreateCopyResultCallback(&error));
    392   content::RunAllBlockingPoolTasksUntilIdle();
    393   EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, error);
    394 }
    395 
    396 TEST_F(CopyOperationTest, CopyDirectory) {
    397   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/Directory 1"));
    398   base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/New Directory"));
    399 
    400   ResourceEntry entry;
    401   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
    402   ASSERT_TRUE(entry.file_info().is_directory());
    403   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path.DirName(), &entry));
    404   ASSERT_TRUE(entry.file_info().is_directory());
    405 
    406   FileError error = FILE_ERROR_OK;
    407   operation_->Copy(src_path,
    408                    dest_path,
    409                    false,
    410                    google_apis::test_util::CreateCopyResultCallback(&error));
    411   content::RunAllBlockingPoolTasksUntilIdle();
    412   EXPECT_EQ(FILE_ERROR_NOT_A_FILE, error);
    413 }
    414 
    415 TEST_F(CopyOperationTest, PreserveLastModified) {
    416   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
    417   base::FilePath dest_path(FILE_PATH_LITERAL("drive/root/File 2.txt"));
    418 
    419   ResourceEntry entry;
    420   ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
    421   ASSERT_EQ(FILE_ERROR_OK,
    422             GetLocalResourceEntry(dest_path.DirName(), &entry));
    423 
    424   FileError error = FILE_ERROR_OK;
    425   operation_->Copy(src_path,
    426                    dest_path,
    427                    true,  // Preserve last modified.
    428                    google_apis::test_util::CreateCopyResultCallback(&error));
    429   content::RunAllBlockingPoolTasksUntilIdle();
    430   EXPECT_EQ(FILE_ERROR_OK, error);
    431 
    432   ResourceEntry entry2;
    433   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &entry));
    434   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &entry2));
    435   EXPECT_EQ(entry.file_info().last_modified(),
    436             entry2.file_info().last_modified());
    437 }
    438 
    439 TEST_F(CopyOperationTest, WaitForSyncComplete) {
    440   // Create a directory locally.
    441   base::FilePath src_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
    442   base::FilePath directory_path(FILE_PATH_LITERAL("drive/root/New Directory"));
    443   base::FilePath dest_path = directory_path.AppendASCII("File 1.txt");
    444 
    445   ResourceEntry directory_parent;
    446   EXPECT_EQ(FILE_ERROR_OK,
    447             GetLocalResourceEntry(directory_path.DirName(), &directory_parent));
    448 
    449   ResourceEntry directory;
    450   directory.set_parent_local_id(directory_parent.local_id());
    451   directory.set_title(directory_path.BaseName().AsUTF8Unsafe());
    452   directory.mutable_file_info()->set_is_directory(true);
    453   directory.set_metadata_edit_state(ResourceEntry::DIRTY);
    454 
    455   std::string directory_local_id;
    456   FileError error = FILE_ERROR_FAILED;
    457   base::PostTaskAndReplyWithResult(
    458       blocking_task_runner(),
    459       FROM_HERE,
    460       base::Bind(&internal::ResourceMetadata::AddEntry,
    461                  base::Unretained(metadata()), directory, &directory_local_id),
    462       google_apis::test_util::CreateCopyResultCallback(&error));
    463   content::RunAllBlockingPoolTasksUntilIdle();
    464   EXPECT_EQ(FILE_ERROR_OK, error);
    465 
    466   // Try to copy a file to the new directory which lacks resource ID.
    467   // This should result in waiting for the directory to sync.
    468   std::string waited_local_id;
    469   FileOperationCallback pending_callback;
    470   delegate()->set_wait_for_sync_complete_handler(
    471       base::Bind(&CopyWaitForSyncCompleteArguments,
    472                  &waited_local_id, &pending_callback));
    473 
    474   FileError copy_error = FILE_ERROR_FAILED;
    475   operation_->Copy(src_path,
    476                    dest_path,
    477                    true,  // Preserve last modified.
    478                    google_apis::test_util::CreateCopyResultCallback(
    479                        &copy_error));
    480   content::RunAllBlockingPoolTasksUntilIdle();
    481   EXPECT_EQ(directory_local_id, waited_local_id);
    482   ASSERT_FALSE(pending_callback.is_null());
    483 
    484   // Add a new directory to the server and store the resource ID locally.
    485   google_apis::GDataErrorCode status = google_apis::GDATA_OTHER_ERROR;
    486   scoped_ptr<google_apis::FileResource> file_resource;
    487   fake_service()->AddNewDirectory(
    488       directory_parent.resource_id(),
    489       directory.title(),
    490       DriveServiceInterface::AddNewDirectoryOptions(),
    491       google_apis::test_util::CreateCopyResultCallback(
    492           &status, &file_resource));
    493   content::RunAllBlockingPoolTasksUntilIdle();
    494   EXPECT_EQ(google_apis::HTTP_CREATED, status);
    495   ASSERT_TRUE(file_resource);
    496 
    497   directory.set_local_id(directory_local_id);
    498   directory.set_resource_id(file_resource->file_id());
    499   base::PostTaskAndReplyWithResult(
    500       blocking_task_runner(),
    501       FROM_HERE,
    502       base::Bind(&internal::ResourceMetadata::RefreshEntry,
    503                  base::Unretained(metadata()), directory),
    504       google_apis::test_util::CreateCopyResultCallback(&error));
    505   content::RunAllBlockingPoolTasksUntilIdle();
    506   EXPECT_EQ(FILE_ERROR_OK, error);
    507 
    508   // Resume the copy operation.
    509   pending_callback.Run(FILE_ERROR_OK);
    510   content::RunAllBlockingPoolTasksUntilIdle();
    511 
    512   EXPECT_EQ(FILE_ERROR_OK, copy_error);
    513   ResourceEntry entry;
    514   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &entry));
    515 }
    516 
    517 }  // namespace file_system
    518 }  // namespace drive
    519