Home | History | Annotate | Download | only in drive
      1 // Copyright (c) 2012 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/resource_metadata.h"
      6 
      7 #include <algorithm>
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/files/scoped_temp_dir.h"
     12 #include "base/sequenced_task_runner.h"
     13 #include "base/threading/sequenced_worker_pool.h"
     14 #include "base/threading/thread_restrictions.h"
     15 #include "chrome/browser/chromeos/drive/drive.pb.h"
     16 #include "chrome/browser/chromeos/drive/file_system_util.h"
     17 #include "chrome/browser/chromeos/drive/test_util.h"
     18 #include "chrome/browser/google_apis/test_util.h"
     19 #include "content/public/browser/browser_thread.h"
     20 #include "content/public/test/test_browser_thread_bundle.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 namespace drive {
     24 namespace internal {
     25 namespace {
     26 
     27 const char kTestRootResourceId[] = "test_root";
     28 
     29 // The changestamp of the resource metadata used in
     30 // ResourceMetadataTest.
     31 const int64 kTestChangestamp = 100;
     32 
     33 // Returns the sorted base names from |entries|.
     34 std::vector<std::string> GetSortedBaseNames(
     35     const ResourceEntryVector& entries) {
     36   std::vector<std::string> base_names;
     37   for (size_t i = 0; i < entries.size(); ++i)
     38     base_names.push_back(entries[i].base_name());
     39   std::sort(base_names.begin(), base_names.end());
     40 
     41   return base_names;
     42 }
     43 
     44 // Creates a ResourceEntry for a directory.
     45 ResourceEntry CreateDirectoryEntry(const std::string& title,
     46                                    const std::string& parent_resource_id) {
     47   ResourceEntry entry;
     48   entry.set_title(title);
     49   entry.set_resource_id("resource_id:" + title);
     50   entry.set_parent_resource_id(parent_resource_id);
     51   entry.mutable_file_info()->set_is_directory(true);
     52   entry.mutable_directory_specific_info()->set_changestamp(kTestChangestamp);
     53   return entry;
     54 }
     55 
     56 // Creates a ResourceEntry for a file.
     57 ResourceEntry CreateFileEntry(const std::string& title,
     58                               const std::string& parent_resource_id) {
     59   ResourceEntry entry;
     60   entry.set_title(title);
     61   entry.set_resource_id("resource_id:" + title);
     62   entry.set_parent_resource_id(parent_resource_id);
     63   entry.mutable_file_info()->set_is_directory(false);
     64   entry.mutable_file_info()->set_size(1024);
     65   entry.mutable_file_specific_info()->set_md5("md5:" + title);
     66   return entry;
     67 }
     68 
     69 // Creates the following files/directories
     70 // drive/root/dir1/
     71 // drive/root/dir2/
     72 // drive/root/dir1/dir3/
     73 // drive/root/dir1/file4
     74 // drive/root/dir1/file5
     75 // drive/root/dir2/file6
     76 // drive/root/dir2/file7
     77 // drive/root/dir2/file8
     78 // drive/root/dir1/dir3/file9
     79 // drive/root/dir1/dir3/file10
     80 void SetUpEntries(ResourceMetadata* resource_metadata) {
     81   // Create mydrive root directory.
     82   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
     83       util::CreateMyDriveRootEntry(kTestRootResourceId)));
     84 
     85   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
     86       CreateDirectoryEntry("dir1", kTestRootResourceId)));
     87   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
     88       CreateDirectoryEntry("dir2", kTestRootResourceId)));
     89 
     90   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
     91       CreateDirectoryEntry("dir3", "resource_id:dir1")));
     92   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
     93       CreateFileEntry("file4", "resource_id:dir1")));
     94   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
     95       CreateFileEntry("file5", "resource_id:dir1")));
     96 
     97   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
     98       CreateFileEntry("file6", "resource_id:dir2")));
     99   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
    100       CreateFileEntry("file7", "resource_id:dir2")));
    101   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
    102       CreateFileEntry("file8", "resource_id:dir2")));
    103 
    104   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
    105       CreateFileEntry("file9", "resource_id:dir3")));
    106   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
    107       CreateFileEntry("file10", "resource_id:dir3")));
    108 
    109   ASSERT_EQ(FILE_ERROR_OK,
    110             resource_metadata->SetLargestChangestamp(kTestChangestamp));
    111 }
    112 
    113 }  // namespace
    114 
    115 // Tests for methods invoked from the UI thread.
    116 class ResourceMetadataTestOnUIThread : public testing::Test {
    117  protected:
    118   virtual void SetUp() OVERRIDE {
    119     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    120 
    121     base::ThreadRestrictions::SetIOAllowed(false);  // For strict thread check.
    122     scoped_refptr<base::SequencedWorkerPool> pool =
    123         content::BrowserThread::GetBlockingPool();
    124     blocking_task_runner_ =
    125         pool->GetSequencedTaskRunner(pool->GetSequenceToken());
    126 
    127     metadata_storage_.reset(new ResourceMetadataStorage(
    128         temp_dir_.path(), blocking_task_runner_.get()));
    129     bool success = false;
    130     base::PostTaskAndReplyWithResult(
    131         blocking_task_runner_.get(),
    132         FROM_HERE,
    133         base::Bind(&ResourceMetadataStorage::Initialize,
    134                    base::Unretained(metadata_storage_.get())),
    135         google_apis::test_util::CreateCopyResultCallback(&success));
    136     test_util::RunBlockingPoolTask();
    137     ASSERT_TRUE(success);
    138 
    139     resource_metadata_.reset(new ResourceMetadata(metadata_storage_.get(),
    140                                                   blocking_task_runner_));
    141 
    142     FileError error = FILE_ERROR_FAILED;
    143     base::PostTaskAndReplyWithResult(
    144         blocking_task_runner_.get(),
    145         FROM_HERE,
    146         base::Bind(&ResourceMetadata::Initialize,
    147                    base::Unretained(resource_metadata_.get())),
    148         google_apis::test_util::CreateCopyResultCallback(&error));
    149     test_util::RunBlockingPoolTask();
    150     ASSERT_EQ(FILE_ERROR_OK, error);
    151 
    152     blocking_task_runner_->PostTask(
    153         FROM_HERE,
    154         base::Bind(&SetUpEntries,
    155                    base::Unretained(resource_metadata_.get())));
    156     test_util::RunBlockingPoolTask();
    157   }
    158 
    159   virtual void TearDown() OVERRIDE {
    160     metadata_storage_.reset();
    161     resource_metadata_.reset();
    162     base::ThreadRestrictions::SetIOAllowed(true);
    163   }
    164 
    165   // Gets the resource entry by path synchronously. Returns NULL on failure.
    166   scoped_ptr<ResourceEntry> GetResourceEntryByPathSync(
    167       const base::FilePath& file_path) {
    168     FileError error = FILE_ERROR_OK;
    169     scoped_ptr<ResourceEntry> entry;
    170     resource_metadata_->GetResourceEntryByPathOnUIThread(
    171         file_path,
    172         google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    173     test_util::RunBlockingPoolTask();
    174     EXPECT_TRUE(error == FILE_ERROR_OK || !entry);
    175     return entry.Pass();
    176   }
    177 
    178   // Reads the directory contents by path synchronously. Returns NULL on
    179   // failure.
    180   scoped_ptr<ResourceEntryVector> ReadDirectoryByPathSync(
    181       const base::FilePath& directory_path) {
    182     FileError error = FILE_ERROR_OK;
    183     scoped_ptr<ResourceEntryVector> entries;
    184     resource_metadata_->ReadDirectoryByPathOnUIThread(
    185         directory_path,
    186         google_apis::test_util::CreateCopyResultCallback(&error, &entries));
    187     test_util::RunBlockingPoolTask();
    188     EXPECT_TRUE(error == FILE_ERROR_OK || !entries);
    189     return entries.Pass();
    190   }
    191 
    192   content::TestBrowserThreadBundle thread_bundle_;
    193   base::ScopedTempDir temp_dir_;
    194   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
    195   scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
    196       metadata_storage_;
    197   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
    198       resource_metadata_;
    199 };
    200 
    201 TEST_F(ResourceMetadataTestOnUIThread, LargestChangestamp) {
    202   FileError error = FILE_ERROR_FAILED;
    203   int64 in_changestamp = 123456;
    204   resource_metadata_->SetLargestChangestampOnUIThread(
    205       in_changestamp,
    206       google_apis::test_util::CreateCopyResultCallback(&error));
    207   test_util::RunBlockingPoolTask();
    208   EXPECT_EQ(FILE_ERROR_OK, error);
    209 
    210   int64 out_changestamp = 0;
    211   resource_metadata_->GetLargestChangestampOnUIThread(
    212       google_apis::test_util::CreateCopyResultCallback(&out_changestamp));
    213   test_util::RunBlockingPoolTask();
    214   DCHECK_EQ(in_changestamp, out_changestamp);
    215 }
    216 
    217 TEST_F(ResourceMetadataTestOnUIThread, GetResourceEntryById_RootDirectory) {
    218   // Look up the root directory by its resource ID.
    219   FileError error = FILE_ERROR_FAILED;
    220   scoped_ptr<ResourceEntry> entry;
    221   resource_metadata_->GetResourceEntryByIdOnUIThread(
    222       util::kDriveGrandRootSpecialResourceId,
    223       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    224   test_util::RunBlockingPoolTask();
    225   EXPECT_EQ(FILE_ERROR_OK, error);
    226   ASSERT_TRUE(entry.get());
    227   EXPECT_EQ("drive", entry->base_name());
    228 }
    229 
    230 TEST_F(ResourceMetadataTestOnUIThread, GetResourceEntryById) {
    231   // Confirm that an existing file is found.
    232   FileError error = FILE_ERROR_FAILED;
    233   scoped_ptr<ResourceEntry> entry;
    234   resource_metadata_->GetResourceEntryByIdOnUIThread(
    235       "resource_id:file4",
    236       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    237   test_util::RunBlockingPoolTask();
    238   EXPECT_EQ(FILE_ERROR_OK, error);
    239   ASSERT_TRUE(entry.get());
    240   EXPECT_EQ("file4", entry->base_name());
    241 
    242   // Confirm that a non existing file is not found.
    243   error = FILE_ERROR_FAILED;
    244   entry.reset();
    245   resource_metadata_->GetResourceEntryByIdOnUIThread(
    246       "file:non_existing",
    247       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    248   test_util::RunBlockingPoolTask();
    249   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    250   EXPECT_FALSE(entry.get());
    251 }
    252 
    253 TEST_F(ResourceMetadataTestOnUIThread, GetResourceEntryByPath) {
    254   // Confirm that an existing file is found.
    255   FileError error = FILE_ERROR_FAILED;
    256   scoped_ptr<ResourceEntry> entry;
    257   resource_metadata_->GetResourceEntryByPathOnUIThread(
    258       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
    259       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    260   test_util::RunBlockingPoolTask();
    261   EXPECT_EQ(FILE_ERROR_OK, error);
    262   ASSERT_TRUE(entry.get());
    263   EXPECT_EQ("file4", entry->base_name());
    264 
    265   // Confirm that a non existing file is not found.
    266   error = FILE_ERROR_FAILED;
    267   entry.reset();
    268   resource_metadata_->GetResourceEntryByPathOnUIThread(
    269       base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existing"),
    270       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    271   test_util::RunBlockingPoolTask();
    272   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    273   EXPECT_FALSE(entry.get());
    274 
    275   // Confirm that the root is found.
    276   error = FILE_ERROR_FAILED;
    277   entry.reset();
    278   resource_metadata_->GetResourceEntryByPathOnUIThread(
    279       base::FilePath::FromUTF8Unsafe("drive"),
    280       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    281   test_util::RunBlockingPoolTask();
    282   EXPECT_EQ(FILE_ERROR_OK, error);
    283   EXPECT_TRUE(entry.get());
    284 
    285   // Confirm that a non existing file is not found at the root level.
    286   error = FILE_ERROR_FAILED;
    287   entry.reset();
    288   resource_metadata_->GetResourceEntryByPathOnUIThread(
    289       base::FilePath::FromUTF8Unsafe("non_existing"),
    290       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    291   test_util::RunBlockingPoolTask();
    292   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    293   EXPECT_FALSE(entry.get());
    294 
    295   // Confirm that an entry is not found with a wrong root.
    296   error = FILE_ERROR_FAILED;
    297   entry.reset();
    298   resource_metadata_->GetResourceEntryByPathOnUIThread(
    299       base::FilePath::FromUTF8Unsafe("non_existing/root"),
    300       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    301   test_util::RunBlockingPoolTask();
    302   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    303   EXPECT_FALSE(entry.get());
    304 }
    305 
    306 TEST_F(ResourceMetadataTestOnUIThread, ReadDirectoryByPath) {
    307   // Confirm that an existing directory is found.
    308   FileError error = FILE_ERROR_FAILED;
    309   scoped_ptr<ResourceEntryVector> entries;
    310   resource_metadata_->ReadDirectoryByPathOnUIThread(
    311       base::FilePath::FromUTF8Unsafe("drive/root/dir1"),
    312       google_apis::test_util::CreateCopyResultCallback(&error, &entries));
    313   test_util::RunBlockingPoolTask();
    314   EXPECT_EQ(FILE_ERROR_OK, error);
    315   ASSERT_TRUE(entries.get());
    316   ASSERT_EQ(3U, entries->size());
    317   // The order is not guaranteed so we should sort the base names.
    318   std::vector<std::string> base_names = GetSortedBaseNames(*entries);
    319   EXPECT_EQ("dir3", base_names[0]);
    320   EXPECT_EQ("file4", base_names[1]);
    321   EXPECT_EQ("file5", base_names[2]);
    322 
    323   // Confirm that a non existing directory is not found.
    324   error = FILE_ERROR_FAILED;
    325   entries.reset();
    326   resource_metadata_->ReadDirectoryByPathOnUIThread(
    327       base::FilePath::FromUTF8Unsafe("drive/root/non_existing"),
    328       google_apis::test_util::CreateCopyResultCallback(&error, &entries));
    329   test_util::RunBlockingPoolTask();
    330   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    331   EXPECT_FALSE(entries.get());
    332 
    333   // Confirm that reading a file results in FILE_ERROR_NOT_A_DIRECTORY.
    334   error = FILE_ERROR_FAILED;
    335   entries.reset();
    336   resource_metadata_->ReadDirectoryByPathOnUIThread(
    337       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
    338       google_apis::test_util::CreateCopyResultCallback(&error, &entries));
    339   test_util::RunBlockingPoolTask();
    340   EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
    341   EXPECT_FALSE(entries.get());
    342 }
    343 
    344 TEST_F(ResourceMetadataTestOnUIThread, GetResourceEntryPairByPaths) {
    345   // Confirm that existing two files are found.
    346   scoped_ptr<EntryInfoPairResult> pair_result;
    347   resource_metadata_->GetResourceEntryPairByPathsOnUIThread(
    348       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
    349       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file5"),
    350       google_apis::test_util::CreateCopyResultCallback(&pair_result));
    351   test_util::RunBlockingPoolTask();
    352   // The first entry should be found.
    353   EXPECT_EQ(FILE_ERROR_OK, pair_result->first.error);
    354   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
    355             pair_result->first.path);
    356   ASSERT_TRUE(pair_result->first.entry.get());
    357   EXPECT_EQ("file4", pair_result->first.entry->base_name());
    358   // The second entry should be found.
    359   EXPECT_EQ(FILE_ERROR_OK, pair_result->second.error);
    360   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/file5"),
    361             pair_result->second.path);
    362   ASSERT_TRUE(pair_result->second.entry.get());
    363   EXPECT_EQ("file5", pair_result->second.entry->base_name());
    364 
    365   // Confirm that the first non existent file is not found.
    366   pair_result.reset();
    367   resource_metadata_->GetResourceEntryPairByPathsOnUIThread(
    368       base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existent"),
    369       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file5"),
    370       google_apis::test_util::CreateCopyResultCallback(&pair_result));
    371   test_util::RunBlockingPoolTask();
    372   // The first entry should not be found.
    373   EXPECT_EQ(FILE_ERROR_NOT_FOUND, pair_result->first.error);
    374   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existent"),
    375             pair_result->first.path);
    376   ASSERT_FALSE(pair_result->first.entry.get());
    377   // The second entry should not be found, because the first one failed.
    378   EXPECT_EQ(FILE_ERROR_FAILED, pair_result->second.error);
    379   EXPECT_EQ(base::FilePath(), pair_result->second.path);
    380   ASSERT_FALSE(pair_result->second.entry.get());
    381 
    382   // Confirm that the second non existent file is not found.
    383   pair_result.reset();
    384   resource_metadata_->GetResourceEntryPairByPathsOnUIThread(
    385       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
    386       base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existent"),
    387       google_apis::test_util::CreateCopyResultCallback(&pair_result));
    388   test_util::RunBlockingPoolTask();
    389   // The first entry should be found.
    390   EXPECT_EQ(FILE_ERROR_OK, pair_result->first.error);
    391   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
    392             pair_result->first.path);
    393   ASSERT_TRUE(pair_result->first.entry.get());
    394   EXPECT_EQ("file4", pair_result->first.entry->base_name());
    395   // The second entry should not be found.
    396   EXPECT_EQ(FILE_ERROR_NOT_FOUND, pair_result->second.error);
    397   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existent"),
    398             pair_result->second.path);
    399   ASSERT_FALSE(pair_result->second.entry.get());
    400 }
    401 
    402 TEST_F(ResourceMetadataTestOnUIThread, MoveEntryToDirectory) {
    403   FileError error = FILE_ERROR_FAILED;
    404   base::FilePath drive_file_path;
    405   scoped_ptr<ResourceEntry> entry;
    406 
    407   // Move file8 to drive/dir1.
    408   resource_metadata_->MoveEntryToDirectoryOnUIThread(
    409       base::FilePath::FromUTF8Unsafe("drive/root/dir2/file8"),
    410       base::FilePath::FromUTF8Unsafe("drive/root/dir1"),
    411       google_apis::test_util::CreateCopyResultCallback(
    412           &error, &drive_file_path));
    413   test_util::RunBlockingPoolTask();
    414   EXPECT_EQ(FILE_ERROR_OK, error);
    415   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/file8"),
    416             drive_file_path);
    417 
    418   // Look up the entry by its resource id and make sure it really moved.
    419   resource_metadata_->GetResourceEntryByIdOnUIThread(
    420       "resource_id:file8",
    421       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    422   test_util::RunBlockingPoolTask();
    423   EXPECT_EQ(FILE_ERROR_OK, error);
    424 
    425   // Move non-existent file to drive/dir1. This should fail.
    426   resource_metadata_->MoveEntryToDirectoryOnUIThread(
    427       base::FilePath::FromUTF8Unsafe("drive/root/dir2/file8"),
    428       base::FilePath::FromUTF8Unsafe("drive/root/dir1"),
    429       google_apis::test_util::CreateCopyResultCallback(
    430           &error, &drive_file_path));
    431   test_util::RunBlockingPoolTask();
    432   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    433   EXPECT_EQ(base::FilePath(), drive_file_path);
    434 
    435   // Move existing file to non-existent directory. This should fail.
    436   resource_metadata_->MoveEntryToDirectoryOnUIThread(
    437       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file8"),
    438       base::FilePath::FromUTF8Unsafe("drive/root/dir4"),
    439       google_apis::test_util::CreateCopyResultCallback(
    440           &error, &drive_file_path));
    441   test_util::RunBlockingPoolTask();
    442   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    443   EXPECT_EQ(base::FilePath(), drive_file_path);
    444 
    445   // Move existing file to existing file (non-directory). This should fail.
    446   resource_metadata_->MoveEntryToDirectoryOnUIThread(
    447       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file8"),
    448       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
    449       google_apis::test_util::CreateCopyResultCallback(
    450           &error, &drive_file_path));
    451   test_util::RunBlockingPoolTask();
    452   EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
    453   EXPECT_EQ(base::FilePath(), drive_file_path);
    454 
    455   // Move the file to root.
    456   resource_metadata_->MoveEntryToDirectoryOnUIThread(
    457       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file8"),
    458       base::FilePath::FromUTF8Unsafe("drive/root"),
    459       google_apis::test_util::CreateCopyResultCallback(
    460           &error, &drive_file_path));
    461   test_util::RunBlockingPoolTask();
    462   EXPECT_EQ(FILE_ERROR_OK, error);
    463   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/file8"),
    464             drive_file_path);
    465 
    466   // Move the file from root.
    467   resource_metadata_->MoveEntryToDirectoryOnUIThread(
    468       base::FilePath::FromUTF8Unsafe("drive/root/file8"),
    469       base::FilePath::FromUTF8Unsafe("drive/root/dir2"),
    470       google_apis::test_util::CreateCopyResultCallback(
    471           &error, &drive_file_path));
    472   test_util::RunBlockingPoolTask();
    473   EXPECT_EQ(FILE_ERROR_OK, error);
    474   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir2/file8"),
    475             drive_file_path);
    476 
    477   // Make sure file is still ok.
    478   resource_metadata_->GetResourceEntryByIdOnUIThread(
    479       "resource_id:file8",
    480       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    481   test_util::RunBlockingPoolTask();
    482   EXPECT_EQ(FILE_ERROR_OK, error);
    483 }
    484 
    485 TEST_F(ResourceMetadataTestOnUIThread, RenameEntry) {
    486   FileError error = FILE_ERROR_FAILED;
    487   base::FilePath drive_file_path;
    488   scoped_ptr<ResourceEntry> entry;
    489 
    490   // Rename file8 to file11.
    491   resource_metadata_->RenameEntryOnUIThread(
    492       base::FilePath::FromUTF8Unsafe("drive/root/dir2/file8"),
    493       "file11",
    494       google_apis::test_util::CreateCopyResultCallback(
    495           &error, &drive_file_path));
    496   test_util::RunBlockingPoolTask();
    497   EXPECT_EQ(FILE_ERROR_OK, error);
    498   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir2/file11"),
    499             drive_file_path);
    500 
    501   // Lookup the file by resource id to make sure the file actually got renamed.
    502   resource_metadata_->GetResourceEntryByIdOnUIThread(
    503       "resource_id:file8",
    504       google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    505   test_util::RunBlockingPoolTask();
    506   EXPECT_EQ(FILE_ERROR_OK, error);
    507 
    508   // Rename to file7 to force a duplicate name.
    509   resource_metadata_->RenameEntryOnUIThread(
    510       base::FilePath::FromUTF8Unsafe("drive/root/dir2/file11"),
    511       "file7",
    512       google_apis::test_util::CreateCopyResultCallback(
    513           &error, &drive_file_path));
    514   test_util::RunBlockingPoolTask();
    515   EXPECT_EQ(FILE_ERROR_OK, error);
    516   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir2/file7 (1)"),
    517             drive_file_path);
    518 
    519   // Rename to same name. This should fail.
    520   resource_metadata_->RenameEntryOnUIThread(
    521       base::FilePath::FromUTF8Unsafe("drive/root/dir2/file7 (1)"),
    522       "file7 (1)",
    523       google_apis::test_util::CreateCopyResultCallback(
    524           &error, &drive_file_path));
    525   test_util::RunBlockingPoolTask();
    526   EXPECT_EQ(FILE_ERROR_EXISTS, error);
    527   EXPECT_EQ(base::FilePath(), drive_file_path);
    528 
    529   // Rename non-existent.
    530   resource_metadata_->RenameEntryOnUIThread(
    531       base::FilePath::FromUTF8Unsafe("drive/root/dir2/file11"),
    532       "file11",
    533       google_apis::test_util::CreateCopyResultCallback(
    534           &error, &drive_file_path));
    535   test_util::RunBlockingPoolTask();
    536   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    537   EXPECT_EQ(base::FilePath(), drive_file_path);
    538 }
    539 
    540 TEST_F(ResourceMetadataTestOnUIThread, RefreshDirectory_EmptyMap) {
    541   base::FilePath kDirectoryPath(FILE_PATH_LITERAL("drive/root/dir1"));
    542   const int64 kNewChangestamp = kTestChangestamp + 1;
    543 
    544   // Read the directory.
    545   FileError error = FILE_ERROR_FAILED;
    546   scoped_ptr<ResourceEntryVector> entries;
    547   entries = ReadDirectoryByPathSync(base::FilePath(kDirectoryPath));
    548   ASSERT_TRUE(entries.get());
    549   // "file4", "file5", "dir3" should exist in drive/dir1.
    550   ASSERT_EQ(3U, entries->size());
    551   std::vector<std::string> base_names = GetSortedBaseNames(*entries);
    552   EXPECT_EQ("dir3", base_names[0]);
    553   EXPECT_EQ("file4", base_names[1]);
    554   EXPECT_EQ("file5", base_names[2]);
    555 
    556   // Get the directory.
    557   scoped_ptr<ResourceEntry> dir1_proto;
    558   dir1_proto = GetResourceEntryByPathSync(kDirectoryPath);
    559   ASSERT_TRUE(dir1_proto.get());
    560   // The changestamp should be initially kTestChangestamp.
    561   EXPECT_EQ(kTestChangestamp,
    562             dir1_proto->directory_specific_info().changestamp());
    563 
    564   // Update the directory with an empty map.
    565   base::FilePath file_path;
    566   ResourceEntryMap entry_map;
    567   resource_metadata_->RefreshDirectoryOnUIThread(
    568       DirectoryFetchInfo(dir1_proto->resource_id(), kNewChangestamp),
    569       entry_map,
    570       google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
    571   test_util::RunBlockingPoolTask();
    572   EXPECT_EQ(FILE_ERROR_OK, error);
    573   EXPECT_EQ(kDirectoryPath, file_path);
    574 
    575   // Get the directory again.
    576   dir1_proto = GetResourceEntryByPathSync(kDirectoryPath);
    577   ASSERT_TRUE(dir1_proto.get());
    578   // The new changestamp should be set.
    579   EXPECT_EQ(kNewChangestamp,
    580             dir1_proto->directory_specific_info().changestamp());
    581 
    582   // Read the directory again.
    583   entries = ReadDirectoryByPathSync(base::FilePath(kDirectoryPath));
    584   ASSERT_TRUE(entries.get());
    585 }
    586 
    587 TEST_F(ResourceMetadataTestOnUIThread, RefreshDirectory_NonEmptyMap) {
    588   base::FilePath kDirectoryPath(FILE_PATH_LITERAL("drive/root/dir1"));
    589   const int64 kNewChangestamp = kTestChangestamp + 1;
    590 
    591   // Read the directory.
    592   FileError error = FILE_ERROR_FAILED;
    593   scoped_ptr<ResourceEntryVector> entries;
    594   entries = ReadDirectoryByPathSync(kDirectoryPath);
    595   ASSERT_TRUE(entries.get());
    596   // "file4", "file5", "dir3" should exist in drive/dir1.
    597   ASSERT_EQ(3U, entries->size());
    598   std::vector<std::string> base_names = GetSortedBaseNames(*entries);
    599   EXPECT_EQ("dir3", base_names[0]);
    600   EXPECT_EQ("file4", base_names[1]);
    601   EXPECT_EQ("file5", base_names[2]);
    602 
    603   // Get the directory dir1.
    604   scoped_ptr<ResourceEntry> dir1_proto;
    605   dir1_proto = GetResourceEntryByPathSync(kDirectoryPath);
    606   ASSERT_TRUE(dir1_proto.get());
    607   // The changestamp should be initially kTestChangestamp.
    608   EXPECT_EQ(kTestChangestamp,
    609             dir1_proto->directory_specific_info().changestamp());
    610 
    611   // Get the directory dir2 (existing non-child directory).
    612   // This directory will be moved to "drive/dir1/dir2".
    613   scoped_ptr<ResourceEntry> dir2_proto;
    614   dir2_proto = GetResourceEntryByPathSync(
    615       base::FilePath::FromUTF8Unsafe("drive/root/dir2"));
    616   ASSERT_TRUE(dir2_proto.get());
    617   EXPECT_EQ(kTestChangestamp,
    618             dir2_proto->directory_specific_info().changestamp());
    619   // Change the parent resource ID, as dir2 will be moved to "drive/dir1/dir2".
    620   dir2_proto->set_parent_resource_id(dir1_proto->resource_id());
    621 
    622   // Get the directory dir3 (existing child directory).
    623   // This directory will remain as "drive/dir1/dir3".
    624   scoped_ptr<ResourceEntry> dir3_proto;
    625   dir3_proto = GetResourceEntryByPathSync(
    626       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"));
    627   ASSERT_TRUE(dir3_proto.get());
    628   EXPECT_EQ(kTestChangestamp,
    629             dir3_proto->directory_specific_info().changestamp());
    630 
    631   // Create a map.
    632   ResourceEntryMap entry_map;
    633 
    634   // Add a new file to the map.
    635   ResourceEntry new_file;
    636   new_file.set_title("new_file");
    637   new_file.set_resource_id("new_file_id");
    638   new_file.set_parent_resource_id(dir1_proto->resource_id());
    639   entry_map["new_file_id"] = new_file;
    640 
    641   // Add a new directory to the map.
    642   ResourceEntry new_directory;
    643   new_directory.set_title("new_directory");
    644   new_directory.set_resource_id("new_directory_id");
    645   new_directory.set_parent_resource_id(dir1_proto->resource_id());
    646   new_directory.mutable_file_info()->set_is_directory(true);
    647   entry_map["new_directory_id"] = new_directory;
    648 
    649   // Add dir2 and dir3 as well.
    650   entry_map[dir2_proto->resource_id()] = *dir2_proto;
    651   entry_map[dir3_proto->resource_id()] = *dir3_proto;
    652 
    653   // Update the directory with the map.
    654   base::FilePath file_path;
    655   resource_metadata_->RefreshDirectoryOnUIThread(
    656       DirectoryFetchInfo(dir1_proto->resource_id(), kNewChangestamp),
    657       entry_map,
    658       google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
    659   test_util::RunBlockingPoolTask();
    660   EXPECT_EQ(FILE_ERROR_OK, error);
    661   EXPECT_EQ(kDirectoryPath, file_path);
    662 
    663   // Get the directory again.
    664   dir1_proto = GetResourceEntryByPathSync(kDirectoryPath);
    665   ASSERT_TRUE(dir1_proto.get());
    666   // The new changestamp should be set.
    667   EXPECT_EQ(kNewChangestamp,
    668             dir1_proto->directory_specific_info().changestamp());
    669 
    670   // Read the directory again.
    671   entries = ReadDirectoryByPathSync(kDirectoryPath);
    672   ASSERT_TRUE(entries.get());
    673   // "new_file", "new_directory", "dir2" should now be added.
    674   base_names = GetSortedBaseNames(*entries);
    675   EXPECT_EQ(1, std::count(base_names.begin(), base_names.end(), "dir2"));
    676   EXPECT_EQ(1,
    677             std::count(base_names.begin(), base_names.end(), "new_directory"));
    678   EXPECT_EQ(1,
    679             std::count(base_names.begin(), base_names.end(), "new_file"));
    680 
    681   // Get the new directory.
    682   scoped_ptr<ResourceEntry> new_directory_proto;
    683   new_directory_proto = GetResourceEntryByPathSync(
    684       base::FilePath::FromUTF8Unsafe("drive/root/dir1/new_directory"));
    685   ASSERT_TRUE(new_directory_proto.get());
    686   // The changestamp should be 0 for a new directory.
    687   EXPECT_EQ(0, new_directory_proto->directory_specific_info().changestamp());
    688 
    689   // Get the directory dir3 (existing child directory) again.
    690   dir3_proto = GetResourceEntryByPathSync(
    691       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"));
    692   ASSERT_TRUE(dir3_proto.get());
    693   // The changestamp should not be changed.
    694   EXPECT_EQ(kTestChangestamp,
    695             dir3_proto->directory_specific_info().changestamp());
    696 
    697   // Read the directory dir3. The contents should remain.
    698   // See the comment at Init() for the contents of the dir3.
    699   entries = ReadDirectoryByPathSync(
    700       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"));
    701   ASSERT_TRUE(entries.get());
    702   ASSERT_EQ(2U, entries->size());
    703 
    704   // Get the directory dir2 (existing non-child directory) again using the
    705   // old path.  This should fail, as dir2 is now moved to drive/dir1/dir2.
    706   dir2_proto = GetResourceEntryByPathSync(
    707       base::FilePath::FromUTF8Unsafe("drive/root/dir2"));
    708   ASSERT_FALSE(dir2_proto.get());
    709 
    710   // Get the directory dir2 (existing non-child directory) again using the
    711   // new path. This should succeed.
    712   dir2_proto = GetResourceEntryByPathSync(
    713       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir2"));
    714   ASSERT_TRUE(dir2_proto.get());
    715   // The changestamp should not be changed.
    716   EXPECT_EQ(kTestChangestamp,
    717             dir2_proto->directory_specific_info().changestamp());
    718 
    719   // Read the directory dir2. The contents should remain.
    720   // See the comment at Init() for the contents of the dir2.
    721   entries = ReadDirectoryByPathSync(
    722       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir2"));
    723   ASSERT_TRUE(entries.get());
    724   ASSERT_EQ(3U, entries->size());
    725 }
    726 
    727 TEST_F(ResourceMetadataTestOnUIThread, RefreshDirectory_WrongParentResourceId) {
    728   base::FilePath kDirectoryPath(FILE_PATH_LITERAL("drive/root/dir1"));
    729   const int64 kNewChangestamp = kTestChangestamp + 1;
    730 
    731   // Get the directory dir1.
    732   scoped_ptr<ResourceEntry> dir1_proto;
    733   dir1_proto = GetResourceEntryByPathSync(kDirectoryPath);
    734   ASSERT_TRUE(dir1_proto.get());
    735 
    736   // Create a map and add a new file to it.
    737   ResourceEntryMap entry_map;
    738   ResourceEntry new_file;
    739   new_file.set_title("new_file");
    740   new_file.set_resource_id("new_file_id");
    741   // Set a random parent resource ID. This entry should not be added because
    742   // the parent resource ID does not match dir1_proto->resource_id().
    743   new_file.set_parent_resource_id("some-random-resource-id");
    744   entry_map["new_file_id"] = new_file;
    745 
    746   // Update the directory with the map.
    747   base::FilePath file_path;
    748   FileError error = FILE_ERROR_FAILED;
    749   resource_metadata_->RefreshDirectoryOnUIThread(
    750       DirectoryFetchInfo(dir1_proto->resource_id(), kNewChangestamp),
    751       entry_map,
    752       google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
    753   test_util::RunBlockingPoolTask();
    754   EXPECT_EQ(FILE_ERROR_OK, error);
    755   EXPECT_EQ(kDirectoryPath, file_path);
    756 
    757   // Read the directory. Confirm that the new file is not added.
    758   scoped_ptr<ResourceEntryVector> entries;
    759   entries = ReadDirectoryByPathSync(kDirectoryPath);
    760   ASSERT_TRUE(entries.get());
    761   std::vector<std::string> base_names = GetSortedBaseNames(*entries);
    762   EXPECT_EQ(0, std::count(base_names.begin(), base_names.end(), "new_file"));
    763 }
    764 
    765 TEST_F(ResourceMetadataTestOnUIThread, AddEntry) {
    766   FileError error = FILE_ERROR_FAILED;
    767   base::FilePath drive_file_path;
    768 
    769   // Add a file to dir3.
    770   ResourceEntry file_entry = CreateFileEntry("file100", "resource_id:dir3");
    771   resource_metadata_->AddEntryOnUIThread(
    772       file_entry,
    773       google_apis::test_util::CreateCopyResultCallback(
    774           &error, &drive_file_path));
    775   test_util::RunBlockingPoolTask();
    776   EXPECT_EQ(FILE_ERROR_OK, error);
    777   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"),
    778             drive_file_path);
    779 
    780   // Add a directory.
    781   ResourceEntry dir_entry = CreateDirectoryEntry("dir101", "resource_id:dir1");
    782   resource_metadata_->AddEntryOnUIThread(
    783       dir_entry,
    784       google_apis::test_util::CreateCopyResultCallback(
    785           &error, &drive_file_path));
    786   test_util::RunBlockingPoolTask();
    787   EXPECT_EQ(FILE_ERROR_OK, error);
    788   EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir101"),
    789             drive_file_path);
    790 
    791   // Add to an invalid parent.
    792   ResourceEntry file_entry3 = CreateFileEntry("file103", "resource_id:invalid");
    793   resource_metadata_->AddEntryOnUIThread(
    794       file_entry3,
    795       google_apis::test_util::CreateCopyResultCallback(
    796           &error, &drive_file_path));
    797   test_util::RunBlockingPoolTask();
    798   EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
    799 
    800   // Add an existing file.
    801   resource_metadata_->AddEntryOnUIThread(
    802       file_entry,
    803       google_apis::test_util::CreateCopyResultCallback(
    804           &error, &drive_file_path));
    805   test_util::RunBlockingPoolTask();
    806   EXPECT_EQ(FILE_ERROR_EXISTS, error);
    807 }
    808 
    809 TEST_F(ResourceMetadataTestOnUIThread, Reset) {
    810   // The grand root has "root" which is not empty.
    811   scoped_ptr<ResourceEntryVector> entries;
    812   entries = ReadDirectoryByPathSync(
    813       base::FilePath::FromUTF8Unsafe("drive/root"));
    814   ASSERT_TRUE(entries.get());
    815   ASSERT_FALSE(entries->empty());
    816 
    817   // Reset.
    818   FileError error = FILE_ERROR_FAILED;
    819   resource_metadata_->ResetOnUIThread(
    820       google_apis::test_util::CreateCopyResultCallback(&error));
    821   test_util::RunBlockingPoolTask();
    822   EXPECT_EQ(FILE_ERROR_OK, error);
    823 
    824   base::FilePath drive_file_path;
    825   scoped_ptr<ResourceEntry> entry;
    826 
    827   // change stamp should be reset.
    828   int64 changestamp = -1;
    829   resource_metadata_->GetLargestChangestampOnUIThread(
    830       google_apis::test_util::CreateCopyResultCallback(&changestamp));
    831   test_util::RunBlockingPoolTask();
    832   EXPECT_EQ(0, changestamp);
    833 
    834   // root should continue to exist.
    835   entry = GetResourceEntryByPathSync(base::FilePath::FromUTF8Unsafe("drive"));
    836   ASSERT_TRUE(entry.get());
    837   EXPECT_EQ("drive", entry->base_name());
    838   ASSERT_TRUE(entry->file_info().is_directory());
    839   EXPECT_EQ(util::kDriveGrandRootSpecialResourceId, entry->resource_id());
    840 
    841   // There is "other", which are both empty.
    842   entries = ReadDirectoryByPathSync(base::FilePath::FromUTF8Unsafe("drive"));
    843   ASSERT_TRUE(entries.get());
    844   EXPECT_EQ(1U, entries->size());
    845 
    846   scoped_ptr<ResourceEntryVector> entries_in_other =
    847       ReadDirectoryByPathSync(base::FilePath::FromUTF8Unsafe("drive/other"));
    848   ASSERT_TRUE(entries_in_other.get());
    849   EXPECT_TRUE(entries_in_other->empty());
    850 }
    851 
    852 // Tests for methods running on the blocking task runner.
    853 class ResourceMetadataTest : public testing::Test {
    854  protected:
    855   virtual void SetUp() OVERRIDE {
    856     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    857 
    858     metadata_storage_.reset(new ResourceMetadataStorage(
    859         temp_dir_.path(), base::MessageLoopProxy::current().get()));
    860     ASSERT_TRUE(metadata_storage_->Initialize());
    861 
    862     resource_metadata_.reset(new ResourceMetadata(
    863         metadata_storage_.get(), base::MessageLoopProxy::current()));
    864 
    865     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
    866 
    867     SetUpEntries(resource_metadata_.get());
    868   }
    869 
    870   base::ScopedTempDir temp_dir_;
    871   content::TestBrowserThreadBundle thread_bundle_;
    872   scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
    873       metadata_storage_;
    874   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
    875       resource_metadata_;
    876 };
    877 
    878 TEST_F(ResourceMetadataTest, RefreshEntry) {
    879   base::FilePath drive_file_path;
    880   ResourceEntry entry;
    881 
    882   // Get file9.
    883   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
    884       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &entry));
    885   EXPECT_EQ("file9", entry.base_name());
    886   EXPECT_TRUE(!entry.file_info().is_directory());
    887   EXPECT_EQ("md5:file9", entry.file_specific_info().md5());
    888 
    889   // Rename it.
    890   ResourceEntry file_entry(entry);
    891   file_entry.set_title("file100");
    892   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(file_entry));
    893 
    894   EXPECT_EQ(
    895       "drive/root/dir1/dir3/file100",
    896       resource_metadata_->GetFilePath(file_entry.resource_id()).AsUTF8Unsafe());
    897   entry.Clear();
    898   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
    899       file_entry.resource_id(), &entry));
    900   EXPECT_EQ("file100", entry.base_name());
    901   EXPECT_TRUE(!entry.file_info().is_directory());
    902   EXPECT_EQ("md5:file9", entry.file_specific_info().md5());
    903 
    904   // Update the file md5.
    905   const std::string updated_md5("md5:updated");
    906   file_entry = entry;
    907   file_entry.mutable_file_specific_info()->set_md5(updated_md5);
    908   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(file_entry));
    909 
    910   EXPECT_EQ(
    911       "drive/root/dir1/dir3/file100",
    912       resource_metadata_->GetFilePath(file_entry.resource_id()).AsUTF8Unsafe());
    913   entry.Clear();
    914   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
    915       file_entry.resource_id(), &entry));
    916   EXPECT_EQ("file100", entry.base_name());
    917   EXPECT_TRUE(!entry.file_info().is_directory());
    918   EXPECT_EQ(updated_md5, entry.file_specific_info().md5());
    919 
    920   // Make sure we get the same thing from GetResourceEntryByPath.
    921   entry.Clear();
    922   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
    923       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"), &entry));
    924   EXPECT_EQ("file100", entry.base_name());
    925   ASSERT_TRUE(!entry.file_info().is_directory());
    926   EXPECT_EQ(updated_md5, entry.file_specific_info().md5());
    927 
    928   // Get dir2.
    929   entry.Clear();
    930   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
    931       base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry));
    932   EXPECT_EQ("dir2", entry.base_name());
    933   ASSERT_TRUE(entry.file_info().is_directory());
    934 
    935   // Change the name to dir100 and change the parent to drive/dir1/dir3.
    936   ResourceEntry dir_entry(entry);
    937   dir_entry.set_title("dir100");
    938   dir_entry.set_parent_resource_id("resource_id:dir3");
    939   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(dir_entry));
    940 
    941   EXPECT_EQ(
    942       "drive/root/dir1/dir3/dir100",
    943       resource_metadata_->GetFilePath(dir_entry.resource_id()).AsUTF8Unsafe());
    944   entry.Clear();
    945   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
    946       dir_entry.resource_id(), &entry));
    947   EXPECT_EQ("dir100", entry.base_name());
    948   EXPECT_TRUE(entry.file_info().is_directory());
    949   EXPECT_EQ("resource_id:dir2", entry.resource_id());
    950 
    951   // Make sure the children have moved over. Test file6.
    952   entry.Clear();
    953   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
    954       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/dir100/file6"),
    955       &entry));
    956   EXPECT_EQ("file6", entry.base_name());
    957 
    958   // Make sure dir2 no longer exists.
    959   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath(
    960       base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry));
    961 
    962   // Cannot refresh root.
    963   dir_entry.Clear();
    964   dir_entry.set_resource_id(util::kDriveGrandRootSpecialResourceId);
    965   dir_entry.set_title("new-root-name");
    966   dir_entry.set_parent_resource_id("resource_id:dir1");
    967   EXPECT_EQ(FILE_ERROR_INVALID_OPERATION,
    968             resource_metadata_->RefreshEntry(dir_entry));
    969 }
    970 
    971 TEST_F(ResourceMetadataTest, GetChildDirectories) {
    972   std::set<base::FilePath> child_directories;
    973 
    974   // file9: not a directory, so no children.
    975   resource_metadata_->GetChildDirectories("resource_id:file9",
    976                                           &child_directories);
    977   EXPECT_TRUE(child_directories.empty());
    978 
    979   // dir2: no child directories.
    980   resource_metadata_->GetChildDirectories("resource_id:dir2",
    981                                           &child_directories);
    982   EXPECT_TRUE(child_directories.empty());
    983 
    984   // dir1: dir3 is the only child
    985   resource_metadata_->GetChildDirectories("resource_id:dir1",
    986                                           &child_directories);
    987   EXPECT_EQ(1u, child_directories.size());
    988   EXPECT_EQ(1u, child_directories.count(
    989       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3")));
    990   child_directories.clear();
    991 
    992   // Add a few more directories to make sure deeper nesting works.
    993   // dir2/dir100
    994   // dir2/dir101
    995   // dir2/dir101/dir102
    996   // dir2/dir101/dir103
    997   // dir2/dir101/dir104
    998   // dir2/dir101/dir102/dir105
    999   // dir2/dir101/dir102/dir105/dir106
   1000   // dir2/dir101/dir102/dir105/dir106/dir107
   1001   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1002       CreateDirectoryEntry("dir100", "resource_id:dir2")));
   1003   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1004       CreateDirectoryEntry("dir101", "resource_id:dir2")));
   1005   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1006       CreateDirectoryEntry("dir102", "resource_id:dir101")));
   1007   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1008       CreateDirectoryEntry("dir103", "resource_id:dir101")));
   1009   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1010       CreateDirectoryEntry("dir104", "resource_id:dir101")));
   1011   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1012       CreateDirectoryEntry("dir105", "resource_id:dir102")));
   1013   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1014       CreateDirectoryEntry("dir106", "resource_id:dir105")));
   1015   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
   1016       CreateDirectoryEntry("dir107", "resource_id:dir106")));
   1017 
   1018   resource_metadata_->GetChildDirectories("resource_id:dir2",
   1019                                           &child_directories);
   1020   EXPECT_EQ(8u, child_directories.size());
   1021   EXPECT_EQ(1u, child_directories.count(base::FilePath::FromUTF8Unsafe(
   1022       "drive/root/dir2/dir101")));
   1023   EXPECT_EQ(1u, child_directories.count(base::FilePath::FromUTF8Unsafe(
   1024       "drive/root/dir2/dir101/dir104")));
   1025   EXPECT_EQ(1u, child_directories.count(base::FilePath::FromUTF8Unsafe(
   1026       "drive/root/dir2/dir101/dir102/dir105/dir106/dir107")));
   1027 }
   1028 
   1029 TEST_F(ResourceMetadataTest, RemoveEntry) {
   1030   // Make sure file9 is found.
   1031   const std::string file9_resource_id = "resource_id:file9";
   1032   ResourceEntry entry;
   1033   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
   1034       file9_resource_id, &entry));
   1035   EXPECT_EQ("file9", entry.base_name());
   1036 
   1037   // Remove file9.
   1038   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(file9_resource_id));
   1039 
   1040   // file9 should no longer exist.
   1041   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
   1042       file9_resource_id, &entry));
   1043 
   1044   // Look for dir3.
   1045   const std::string dir3_resource_id = "resource_id:dir3";
   1046   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
   1047       dir3_resource_id, &entry));
   1048   EXPECT_EQ("dir3", entry.base_name());
   1049 
   1050   // Remove dir3.
   1051   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(dir3_resource_id));
   1052 
   1053   // dir3 should no longer exist.
   1054   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
   1055       dir3_resource_id, &entry));
   1056 
   1057   // Remove unknown resource_id using RemoveEntry.
   1058   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->RemoveEntry("foo"));
   1059 
   1060   // Try removing root. This should fail.
   1061   EXPECT_EQ(FILE_ERROR_ACCESS_DENIED, resource_metadata_->RemoveEntry(
   1062       util::kDriveGrandRootSpecialResourceId));
   1063 }
   1064 
   1065 TEST_F(ResourceMetadataTest, Iterate) {
   1066   scoped_ptr<ResourceMetadata::Iterator> it = resource_metadata_->GetIterator();
   1067   ASSERT_TRUE(it);
   1068 
   1069   int file_count = 0, directory_count = 0;
   1070   for (; !it->IsAtEnd(); it->Advance()) {
   1071     if (!it->Get().file_info().is_directory())
   1072       ++file_count;
   1073     else
   1074       ++directory_count;
   1075   }
   1076 
   1077   EXPECT_EQ(7, file_count);
   1078   EXPECT_EQ(6, directory_count);
   1079 }
   1080 
   1081 }  // namespace internal
   1082 }  // namespace drive
   1083