Home | History | Annotate | Download | only in drive
      1 // Copyright 2014 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/directory_loader.h"
      6 
      7 #include "base/callback_helpers.h"
      8 #include "base/files/scoped_temp_dir.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/prefs/testing_pref_service.h"
     11 #include "base/run_loop.h"
     12 #include "chrome/browser/chromeos/drive/change_list_loader.h"
     13 #include "chrome/browser/chromeos/drive/change_list_loader_observer.h"
     14 #include "chrome/browser/chromeos/drive/file_cache.h"
     15 #include "chrome/browser/chromeos/drive/file_system_util.h"
     16 #include "chrome/browser/chromeos/drive/job_scheduler.h"
     17 #include "chrome/browser/chromeos/drive/resource_metadata.h"
     18 #include "chrome/browser/chromeos/drive/test_util.h"
     19 #include "chrome/browser/drive/event_logger.h"
     20 #include "chrome/browser/drive/fake_drive_service.h"
     21 #include "chrome/browser/drive/test_util.h"
     22 #include "content/public/test/test_browser_thread_bundle.h"
     23 #include "google_apis/drive/drive_api_parser.h"
     24 #include "google_apis/drive/test_util.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 
     27 namespace drive {
     28 namespace internal {
     29 
     30 namespace {
     31 
     32 class TestDirectoryLoaderObserver : public ChangeListLoaderObserver {
     33  public:
     34   explicit TestDirectoryLoaderObserver(DirectoryLoader* loader)
     35       : loader_(loader) {
     36     loader_->AddObserver(this);
     37   }
     38 
     39   virtual ~TestDirectoryLoaderObserver() {
     40     loader_->RemoveObserver(this);
     41   }
     42 
     43   const std::set<base::FilePath>& changed_directories() const {
     44     return changed_directories_;
     45   }
     46   void clear_changed_directories() { changed_directories_.clear(); }
     47 
     48   // ChageListObserver overrides:
     49   virtual void OnDirectoryReloaded(
     50       const base::FilePath& directory_path) OVERRIDE {
     51     changed_directories_.insert(directory_path);
     52   }
     53 
     54  private:
     55   DirectoryLoader* loader_;
     56   std::set<base::FilePath> changed_directories_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(TestDirectoryLoaderObserver);
     59 };
     60 
     61 void AccumulateReadDirectoryResult(ResourceEntryVector* out_entries,
     62                                    scoped_ptr<ResourceEntryVector> entries) {
     63   ASSERT_TRUE(entries);
     64   out_entries->insert(out_entries->end(), entries->begin(), entries->end());
     65 }
     66 
     67 }  // namespace
     68 
     69 class DirectoryLoaderTest : public testing::Test {
     70  protected:
     71   virtual void SetUp() OVERRIDE {
     72     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     73     pref_service_.reset(new TestingPrefServiceSimple);
     74     test_util::RegisterDrivePrefs(pref_service_->registry());
     75 
     76     logger_.reset(new EventLogger);
     77 
     78     drive_service_.reset(new FakeDriveService);
     79     ASSERT_TRUE(test_util::SetUpTestEntries(drive_service_.get()));
     80 
     81     scheduler_.reset(new JobScheduler(pref_service_.get(),
     82                                       logger_.get(),
     83                                       drive_service_.get(),
     84                                       base::MessageLoopProxy::current().get()));
     85     metadata_storage_.reset(new ResourceMetadataStorage(
     86         temp_dir_.path(), base::MessageLoopProxy::current().get()));
     87     ASSERT_TRUE(metadata_storage_->Initialize());
     88 
     89     cache_.reset(new FileCache(metadata_storage_.get(),
     90                                temp_dir_.path(),
     91                                base::MessageLoopProxy::current().get(),
     92                                NULL /* free_disk_space_getter */));
     93     ASSERT_TRUE(cache_->Initialize());
     94 
     95     metadata_.reset(new ResourceMetadata(
     96         metadata_storage_.get(), cache_.get(),
     97         base::MessageLoopProxy::current().get()));
     98     ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
     99 
    100     about_resource_loader_.reset(new AboutResourceLoader(scheduler_.get()));
    101     loader_controller_.reset(new LoaderController);
    102     directory_loader_.reset(
    103         new DirectoryLoader(logger_.get(),
    104                              base::MessageLoopProxy::current().get(),
    105                              metadata_.get(),
    106                              scheduler_.get(),
    107                              about_resource_loader_.get(),
    108                              loader_controller_.get()));
    109   }
    110 
    111   // Adds a new file to the root directory of the service.
    112   scoped_ptr<google_apis::FileResource> AddNewFile(const std::string& title) {
    113     google_apis::GDataErrorCode error = google_apis::GDATA_FILE_ERROR;
    114     scoped_ptr<google_apis::FileResource> entry;
    115     drive_service_->AddNewFile(
    116         "text/plain",
    117         "content text",
    118         drive_service_->GetRootResourceId(),
    119         title,
    120         false,  // shared_with_me
    121         google_apis::test_util::CreateCopyResultCallback(&error, &entry));
    122     base::RunLoop().RunUntilIdle();
    123     EXPECT_EQ(google_apis::HTTP_CREATED, error);
    124     return entry.Pass();
    125   }
    126 
    127   content::TestBrowserThreadBundle thread_bundle_;
    128   base::ScopedTempDir temp_dir_;
    129   scoped_ptr<TestingPrefServiceSimple> pref_service_;
    130   scoped_ptr<EventLogger> logger_;
    131   scoped_ptr<FakeDriveService> drive_service_;
    132   scoped_ptr<JobScheduler> scheduler_;
    133   scoped_ptr<ResourceMetadataStorage,
    134              test_util::DestroyHelperForTests> metadata_storage_;
    135   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
    136   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_;
    137   scoped_ptr<AboutResourceLoader> about_resource_loader_;
    138   scoped_ptr<LoaderController> loader_controller_;
    139   scoped_ptr<DirectoryLoader> directory_loader_;
    140 };
    141 
    142 TEST_F(DirectoryLoaderTest, ReadDirectory_GrandRoot) {
    143   TestDirectoryLoaderObserver observer(directory_loader_.get());
    144 
    145   // Load grand root.
    146   FileError error = FILE_ERROR_FAILED;
    147   ResourceEntryVector entries;
    148   directory_loader_->ReadDirectory(
    149       util::GetDriveGrandRootPath(),
    150       base::Bind(&AccumulateReadDirectoryResult, &entries),
    151       google_apis::test_util::CreateCopyResultCallback(&error));
    152   base::RunLoop().RunUntilIdle();
    153   EXPECT_EQ(FILE_ERROR_OK, error);
    154   EXPECT_EQ(0U, observer.changed_directories().size());
    155   observer.clear_changed_directories();
    156 
    157   // My Drive has resource ID.
    158   ResourceEntry entry;
    159   EXPECT_EQ(FILE_ERROR_OK,
    160             metadata_->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
    161                                               &entry));
    162   EXPECT_EQ(drive_service_->GetRootResourceId(), entry.resource_id());
    163 }
    164 
    165 TEST_F(DirectoryLoaderTest, ReadDirectory_MyDrive) {
    166   TestDirectoryLoaderObserver observer(directory_loader_.get());
    167 
    168   // My Drive does not have resource ID yet.
    169   ResourceEntry entry;
    170   EXPECT_EQ(FILE_ERROR_OK,
    171             metadata_->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
    172                                               &entry));
    173   EXPECT_TRUE(entry.resource_id().empty());
    174 
    175   // Load My Drive.
    176   FileError error = FILE_ERROR_FAILED;
    177   ResourceEntryVector entries;
    178   directory_loader_->ReadDirectory(
    179       util::GetDriveMyDriveRootPath(),
    180       base::Bind(&AccumulateReadDirectoryResult, &entries),
    181       google_apis::test_util::CreateCopyResultCallback(&error));
    182   base::RunLoop().RunUntilIdle();
    183   EXPECT_EQ(FILE_ERROR_OK, error);
    184   EXPECT_EQ(1U, observer.changed_directories().count(
    185       util::GetDriveMyDriveRootPath()));
    186 
    187   // My Drive has resource ID.
    188   EXPECT_EQ(FILE_ERROR_OK,
    189             metadata_->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
    190                                               &entry));
    191   EXPECT_EQ(drive_service_->GetRootResourceId(), entry.resource_id());
    192   EXPECT_EQ(drive_service_->about_resource().largest_change_id(),
    193             entry.directory_specific_info().changestamp());
    194 
    195   // My Drive's child is present.
    196   base::FilePath file_path =
    197       util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
    198   EXPECT_EQ(FILE_ERROR_OK,
    199             metadata_->GetResourceEntryByPath(file_path, &entry));
    200 }
    201 
    202 TEST_F(DirectoryLoaderTest, ReadDirectory_MultipleCalls) {
    203   TestDirectoryLoaderObserver observer(directory_loader_.get());
    204 
    205   // Load grand root.
    206   FileError error = FILE_ERROR_FAILED;
    207   ResourceEntryVector entries;
    208   directory_loader_->ReadDirectory(
    209       util::GetDriveGrandRootPath(),
    210       base::Bind(&AccumulateReadDirectoryResult, &entries),
    211       google_apis::test_util::CreateCopyResultCallback(&error));
    212 
    213   // Load grand root again without waiting for the result.
    214   FileError error2 = FILE_ERROR_FAILED;
    215   ResourceEntryVector entries2;
    216   directory_loader_->ReadDirectory(
    217       util::GetDriveGrandRootPath(),
    218       base::Bind(&AccumulateReadDirectoryResult, &entries2),
    219       google_apis::test_util::CreateCopyResultCallback(&error2));
    220   base::RunLoop().RunUntilIdle();
    221 
    222   // Callback is called for each method call.
    223   EXPECT_EQ(FILE_ERROR_OK, error);
    224   EXPECT_EQ(FILE_ERROR_OK, error2);
    225 }
    226 
    227 TEST_F(DirectoryLoaderTest, Lock) {
    228   // Lock the loader.
    229   scoped_ptr<base::ScopedClosureRunner> lock = loader_controller_->GetLock();
    230 
    231   // Start loading.
    232   TestDirectoryLoaderObserver observer(directory_loader_.get());
    233   FileError error = FILE_ERROR_FAILED;
    234   ResourceEntryVector entries;
    235   directory_loader_->ReadDirectory(
    236       util::GetDriveMyDriveRootPath(),
    237       base::Bind(&AccumulateReadDirectoryResult, &entries),
    238       google_apis::test_util::CreateCopyResultCallback(&error));
    239   base::RunLoop().RunUntilIdle();
    240 
    241   // Update is pending due to the lock.
    242   EXPECT_TRUE(observer.changed_directories().empty());
    243 
    244   // Unlock the loader, this should resume the pending udpate.
    245   lock.reset();
    246   base::RunLoop().RunUntilIdle();
    247   EXPECT_EQ(1U, observer.changed_directories().count(
    248       util::GetDriveMyDriveRootPath()));
    249 }
    250 
    251 }  // namespace internal
    252 }  // namespace drive
    253