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 27namespace drive { 28namespace internal { 29 30namespace { 31 32class 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 61void 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 69class 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 142TEST_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 165TEST_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 202TEST_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 227TEST_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