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