download_operation_unittest.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
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/download_operation.h" 6 7#include "base/file_util.h" 8#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h" 9#include "chrome/browser/chromeos/drive/file_cache.h" 10#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h" 11#include "chrome/browser/chromeos/drive/file_system_util.h" 12#include "chrome/browser/drive/fake_drive_service.h" 13#include "chrome/browser/google_apis/test_util.h" 14#include "testing/gtest/include/gtest/gtest.h" 15 16namespace drive { 17namespace file_system { 18 19class DownloadOperationTest : public OperationTestBase { 20 protected: 21 virtual void SetUp() OVERRIDE { 22 OperationTestBase::SetUp(); 23 24 operation_.reset(new DownloadOperation( 25 blocking_task_runner(), observer(), scheduler(), metadata(), cache(), 26 temp_dir())); 27 } 28 29 scoped_ptr<DownloadOperation> operation_; 30}; 31 32TEST_F(DownloadOperationTest, 33 EnsureFileDownloadedByPath_FromServer_EnoughSpace) { 34 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 35 ResourceEntry src_entry; 36 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry)); 37 const int64 file_size = src_entry.file_info().size(); 38 39 // Pretend we have enough space. 40 fake_free_disk_space_getter()->set_default_value( 41 file_size + internal::kMinFreeSpace); 42 43 FileError error = FILE_ERROR_FAILED; 44 base::FilePath file_path; 45 scoped_ptr<ResourceEntry> entry; 46 operation_->EnsureFileDownloadedByPath( 47 file_in_root, 48 ClientContext(USER_INITIATED), 49 GetFileContentInitializedCallback(), 50 google_apis::GetContentCallback(), 51 google_apis::test_util::CreateCopyResultCallback( 52 &error, &file_path, &entry)); 53 test_util::RunBlockingPoolTask(); 54 55 EXPECT_EQ(FILE_ERROR_OK, error); 56 ASSERT_TRUE(entry); 57 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 58 59 // The transfered file is cached and the change of "offline available" 60 // attribute is notified. 61 EXPECT_EQ(1U, observer()->get_changed_paths().size()); 62 EXPECT_EQ(1U, observer()->get_changed_paths().count(file_in_root.DirName())); 63 64 // Verify that readable permission is set. 65 int permission = 0; 66 EXPECT_TRUE(file_util::GetPosixFilePermissions(file_path, &permission)); 67 EXPECT_EQ(file_util::FILE_PERMISSION_READ_BY_USER | 68 file_util::FILE_PERMISSION_WRITE_BY_USER | 69 file_util::FILE_PERMISSION_READ_BY_GROUP | 70 file_util::FILE_PERMISSION_READ_BY_OTHERS, permission); 71} 72 73TEST_F(DownloadOperationTest, 74 EnsureFileDownloadedByPath_FromServer_NoSpaceAtAll) { 75 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 76 77 // Pretend we have no space at all. 78 fake_free_disk_space_getter()->set_default_value(0); 79 80 FileError error = FILE_ERROR_OK; 81 base::FilePath file_path; 82 scoped_ptr<ResourceEntry> entry; 83 operation_->EnsureFileDownloadedByPath( 84 file_in_root, 85 ClientContext(USER_INITIATED), 86 GetFileContentInitializedCallback(), 87 google_apis::GetContentCallback(), 88 google_apis::test_util::CreateCopyResultCallback( 89 &error, &file_path, &entry)); 90 test_util::RunBlockingPoolTask(); 91 92 EXPECT_EQ(FILE_ERROR_NO_LOCAL_SPACE, error); 93} 94 95TEST_F(DownloadOperationTest, 96 EnsureFileDownloadedByPath_FromServer_NoEnoughSpaceButCanFreeUp) { 97 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 98 ResourceEntry src_entry; 99 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry)); 100 const int64 file_size = src_entry.file_info().size(); 101 102 // Pretend we have no space first (checked before downloading a file), 103 // but then start reporting we have space. This is to emulate that 104 // the disk space was freed up by removing temporary files. 105 fake_free_disk_space_getter()->PushFakeValue( 106 file_size + internal::kMinFreeSpace); 107 fake_free_disk_space_getter()->PushFakeValue(0); 108 fake_free_disk_space_getter()->set_default_value( 109 file_size + internal::kMinFreeSpace); 110 111 // Store something of the file size in the temporary cache directory. 112 const std::string content(file_size, 'x'); 113 base::ScopedTempDir temp_dir; 114 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 115 const base::FilePath tmp_file = 116 temp_dir.path().AppendASCII("something.txt"); 117 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(tmp_file, content)); 118 119 FileError error = FILE_ERROR_FAILED; 120 cache()->StoreOnUIThread( 121 "<id>", "<md5>", tmp_file, 122 internal::FileCache::FILE_OPERATION_COPY, 123 google_apis::test_util::CreateCopyResultCallback(&error)); 124 test_util::RunBlockingPoolTask(); 125 EXPECT_EQ(FILE_ERROR_OK, error); 126 127 base::FilePath file_path; 128 scoped_ptr<ResourceEntry> entry; 129 operation_->EnsureFileDownloadedByPath( 130 file_in_root, 131 ClientContext(USER_INITIATED), 132 GetFileContentInitializedCallback(), 133 google_apis::GetContentCallback(), 134 google_apis::test_util::CreateCopyResultCallback( 135 &error, &file_path, &entry)); 136 test_util::RunBlockingPoolTask(); 137 138 EXPECT_EQ(FILE_ERROR_OK, error); 139 ASSERT_TRUE(entry); 140 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 141 142 // The transfered file is cached and the change of "offline available" 143 // attribute is notified. 144 EXPECT_EQ(1U, observer()->get_changed_paths().size()); 145 EXPECT_EQ(1U, observer()->get_changed_paths().count(file_in_root.DirName())); 146 147 // The cache entry should be removed in order to free up space. 148 FileCacheEntry cache_entry; 149 bool result = true; 150 cache()->GetCacheEntryOnUIThread( 151 "<id>", 152 google_apis::test_util::CreateCopyResultCallback(&result, 153 &cache_entry)); 154 test_util::RunBlockingPoolTask(); 155 ASSERT_FALSE(result); 156} 157 158TEST_F(DownloadOperationTest, 159 EnsureFileDownloadedByPath_FromServer_EnoughSpaceButBecomeFull) { 160 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 161 ResourceEntry src_entry; 162 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry)); 163 const int64 file_size = src_entry.file_info().size(); 164 165 // Pretend we have enough space first (checked before downloading a file), 166 // but then start reporting we have not enough space. This is to emulate that 167 // the disk space becomes full after the file is downloaded for some reason 168 // (ex. the actual file was larger than the expected size). 169 fake_free_disk_space_getter()->PushFakeValue( 170 file_size + internal::kMinFreeSpace); 171 fake_free_disk_space_getter()->set_default_value( 172 internal::kMinFreeSpace - 1); 173 174 FileError error = FILE_ERROR_OK; 175 base::FilePath file_path; 176 scoped_ptr<ResourceEntry> entry; 177 operation_->EnsureFileDownloadedByPath( 178 file_in_root, 179 ClientContext(USER_INITIATED), 180 GetFileContentInitializedCallback(), 181 google_apis::GetContentCallback(), 182 google_apis::test_util::CreateCopyResultCallback( 183 &error, &file_path, &entry)); 184 test_util::RunBlockingPoolTask(); 185 186 EXPECT_EQ(FILE_ERROR_NO_LOCAL_SPACE, error); 187} 188 189TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_FromCache) { 190 base::FilePath temp_file; 191 ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir(), &temp_file)); 192 193 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 194 ResourceEntry src_entry; 195 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry)); 196 197 // Store something as cached version of this file. 198 FileError error = FILE_ERROR_OK; 199 cache()->StoreOnUIThread( 200 GetLocalId(file_in_root), 201 src_entry.file_specific_info().md5(), 202 temp_file, 203 internal::FileCache::FILE_OPERATION_COPY, 204 google_apis::test_util::CreateCopyResultCallback(&error)); 205 test_util::RunBlockingPoolTask(); 206 EXPECT_EQ(FILE_ERROR_OK, error); 207 208 base::FilePath file_path; 209 scoped_ptr<ResourceEntry> entry; 210 operation_->EnsureFileDownloadedByPath( 211 file_in_root, 212 ClientContext(USER_INITIATED), 213 GetFileContentInitializedCallback(), 214 google_apis::GetContentCallback(), 215 google_apis::test_util::CreateCopyResultCallback( 216 &error, &file_path, &entry)); 217 test_util::RunBlockingPoolTask(); 218 219 EXPECT_EQ(FILE_ERROR_OK, error); 220 ASSERT_TRUE(entry); 221 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 222} 223 224TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_HostedDocument) { 225 base::FilePath file_in_root(FILE_PATH_LITERAL( 226 "drive/root/Document 1 excludeDir-test.gdoc")); 227 228 FileError error = FILE_ERROR_FAILED; 229 base::FilePath file_path; 230 scoped_ptr<ResourceEntry> entry; 231 operation_->EnsureFileDownloadedByPath( 232 file_in_root, 233 ClientContext(USER_INITIATED), 234 GetFileContentInitializedCallback(), 235 google_apis::GetContentCallback(), 236 google_apis::test_util::CreateCopyResultCallback( 237 &error, &file_path, &entry)); 238 test_util::RunBlockingPoolTask(); 239 240 EXPECT_EQ(FILE_ERROR_OK, error); 241 ASSERT_TRUE(entry); 242 EXPECT_TRUE(entry->file_specific_info().is_hosted_document()); 243 EXPECT_FALSE(file_path.empty()); 244 245 EXPECT_EQ(GURL(entry->file_specific_info().alternate_url()), 246 util::ReadUrlFromGDocFile(file_path)); 247 EXPECT_EQ(entry->resource_id(), util::ReadResourceIdFromGDocFile(file_path)); 248} 249 250TEST_F(DownloadOperationTest, EnsureFileDownloadedByLocalId) { 251 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 252 ResourceEntry src_entry; 253 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry)); 254 255 FileError error = FILE_ERROR_OK; 256 base::FilePath file_path; 257 scoped_ptr<ResourceEntry> entry; 258 operation_->EnsureFileDownloadedByLocalId( 259 GetLocalId(file_in_root), 260 ClientContext(USER_INITIATED), 261 GetFileContentInitializedCallback(), 262 google_apis::GetContentCallback(), 263 google_apis::test_util::CreateCopyResultCallback( 264 &error, &file_path, &entry)); 265 test_util::RunBlockingPoolTask(); 266 267 EXPECT_EQ(FILE_ERROR_OK, error); 268 ASSERT_TRUE(entry); 269 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 270 271 // The transfered file is cached and the change of "offline available" 272 // attribute is notified. 273 EXPECT_EQ(1U, observer()->get_changed_paths().size()); 274 EXPECT_EQ(1U, observer()->get_changed_paths().count(file_in_root.DirName())); 275} 276 277TEST_F(DownloadOperationTest, 278 EnsureFileDownloadedByPath_WithGetContentCallback) { 279 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 280 281 { 282 FileError initialized_error = FILE_ERROR_FAILED; 283 scoped_ptr<ResourceEntry> entry, entry_dontcare; 284 base::FilePath local_path, local_path_dontcare; 285 base::Closure cancel_download; 286 google_apis::test_util::TestGetContentCallback get_content_callback; 287 288 FileError completion_error = FILE_ERROR_FAILED; 289 290 operation_->EnsureFileDownloadedByPath( 291 file_in_root, 292 ClientContext(USER_INITIATED), 293 google_apis::test_util::CreateCopyResultCallback( 294 &initialized_error, &entry, &local_path, &cancel_download), 295 get_content_callback.callback(), 296 google_apis::test_util::CreateCopyResultCallback( 297 &completion_error, &local_path_dontcare, &entry_dontcare)); 298 test_util::RunBlockingPoolTask(); 299 300 // For the first time, file is downloaded from the remote server. 301 // In this case, |local_path| is empty while |cancel_download| is not. 302 EXPECT_EQ(FILE_ERROR_OK, initialized_error); 303 ASSERT_TRUE(entry); 304 ASSERT_TRUE(local_path.empty()); 305 EXPECT_TRUE(!cancel_download.is_null()); 306 // Content is available through the second callback argument. 307 EXPECT_EQ(static_cast<size_t>(entry->file_info().size()), 308 get_content_callback.GetConcatenatedData().size()); 309 EXPECT_EQ(FILE_ERROR_OK, completion_error); 310 311 // The transfered file is cached and the change of "offline available" 312 // attribute is notified. 313 EXPECT_EQ(1U, observer()->get_changed_paths().size()); 314 EXPECT_EQ(1U, 315 observer()->get_changed_paths().count(file_in_root.DirName())); 316 } 317 318 { 319 FileError initialized_error = FILE_ERROR_FAILED; 320 scoped_ptr<ResourceEntry> entry, entry_dontcare; 321 base::FilePath local_path, local_path_dontcare; 322 base::Closure cancel_download; 323 google_apis::test_util::TestGetContentCallback get_content_callback; 324 325 FileError completion_error = FILE_ERROR_FAILED; 326 327 operation_->EnsureFileDownloadedByPath( 328 file_in_root, 329 ClientContext(USER_INITIATED), 330 google_apis::test_util::CreateCopyResultCallback( 331 &initialized_error, &entry, &local_path, &cancel_download), 332 get_content_callback.callback(), 333 google_apis::test_util::CreateCopyResultCallback( 334 &completion_error, &local_path_dontcare, &entry_dontcare)); 335 test_util::RunBlockingPoolTask(); 336 337 // Try second download. In this case, the file should be cached, so 338 // |local_path| should not be empty while |cancel_download| is empty. 339 EXPECT_EQ(FILE_ERROR_OK, initialized_error); 340 ASSERT_TRUE(entry); 341 ASSERT_TRUE(!local_path.empty()); 342 EXPECT_TRUE(cancel_download.is_null()); 343 // The content is available from the cache file. 344 EXPECT_TRUE(get_content_callback.data().empty()); 345 int64 local_file_size = 0; 346 file_util::GetFileSize(local_path, &local_file_size); 347 EXPECT_EQ(entry->file_info().size(), local_file_size); 348 EXPECT_EQ(FILE_ERROR_OK, completion_error); 349 } 350} 351 352TEST_F(DownloadOperationTest, EnsureFileDownloadedByLocalId_FromCache) { 353 base::FilePath temp_file; 354 ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir(), &temp_file)); 355 356 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 357 ResourceEntry src_entry; 358 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry)); 359 360 // Store something as cached version of this file. 361 FileError error = FILE_ERROR_FAILED; 362 cache()->StoreOnUIThread( 363 GetLocalId(file_in_root), 364 src_entry.file_specific_info().md5(), 365 temp_file, 366 internal::FileCache::FILE_OPERATION_COPY, 367 google_apis::test_util::CreateCopyResultCallback(&error)); 368 test_util::RunBlockingPoolTask(); 369 EXPECT_EQ(FILE_ERROR_OK, error); 370 371 // The file is obtained from the cache. 372 // Hence the downloading should work even if the drive service is offline. 373 fake_service()->set_offline(true); 374 375 base::FilePath file_path; 376 scoped_ptr<ResourceEntry> entry; 377 operation_->EnsureFileDownloadedByLocalId( 378 GetLocalId(file_in_root), 379 ClientContext(USER_INITIATED), 380 GetFileContentInitializedCallback(), 381 google_apis::GetContentCallback(), 382 google_apis::test_util::CreateCopyResultCallback( 383 &error, &file_path, &entry)); 384 test_util::RunBlockingPoolTask(); 385 386 EXPECT_EQ(FILE_ERROR_OK, error); 387 ASSERT_TRUE(entry); 388 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 389} 390 391TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_DirtyCache) { 392 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 393 ResourceEntry src_entry; 394 ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry)); 395 396 // Prepare a dirty file to store to cache that has a different size than 397 // stored in resource metadata. 398 base::FilePath dirty_file = temp_dir().AppendASCII("dirty.txt"); 399 size_t dirty_size = src_entry.file_info().size() + 10; 400 google_apis::test_util::WriteStringToFile(dirty_file, 401 std::string(dirty_size, 'x')); 402 403 // Store the file as a cache, marking it to be dirty. 404 FileError error = FILE_ERROR_FAILED; 405 cache()->StoreOnUIThread( 406 GetLocalId(file_in_root), 407 src_entry.file_specific_info().md5(), 408 dirty_file, 409 internal::FileCache::FILE_OPERATION_COPY, 410 google_apis::test_util::CreateCopyResultCallback(&error)); 411 test_util::RunBlockingPoolTask(); 412 EXPECT_EQ(FILE_ERROR_OK, error); 413 cache()->MarkDirtyOnUIThread( 414 GetLocalId(file_in_root), 415 google_apis::test_util::CreateCopyResultCallback(&error)); 416 test_util::RunBlockingPoolTask(); 417 EXPECT_EQ(FILE_ERROR_OK, error); 418 419 // Record values passed to GetFileContentInitializedCallback(). 420 FileError init_error; 421 base::FilePath init_path; 422 scoped_ptr<ResourceEntry> init_entry; 423 base::Closure cancel_callback; 424 425 base::FilePath file_path; 426 scoped_ptr<ResourceEntry> entry; 427 operation_->EnsureFileDownloadedByPath( 428 file_in_root, 429 ClientContext(USER_INITIATED), 430 google_apis::test_util::CreateCopyResultCallback( 431 &init_error, &init_entry, &init_path, &cancel_callback), 432 google_apis::GetContentCallback(), 433 google_apis::test_util::CreateCopyResultCallback( 434 &error, &file_path, &entry)); 435 test_util::RunBlockingPoolTask(); 436 437 EXPECT_EQ(FILE_ERROR_OK, error); 438 // Check that the result of local modification is propagated. 439 EXPECT_EQ(static_cast<int64>(dirty_size), init_entry->file_info().size()); 440 EXPECT_EQ(static_cast<int64>(dirty_size), entry->file_info().size()); 441} 442 443} // namespace file_system 444} // namespace drive 445