Set root resource ID upon full feed update.
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / drive_file_system_unittest.cc
blob9ca023d1ca16d44dd1693cabc412cdfc66110def
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.
5 #include "chrome/browser/chromeos/drive/drive_file_system.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/file_path.h"
12 #include "base/file_util.h"
13 #include "base/json/json_file_value_serializer.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop.h"
16 #include "base/path_service.h"
17 #include "base/scoped_temp_dir.h"
18 #include "base/stringprintf.h"
19 #include "base/threading/sequenced_worker_pool.h"
20 #include "base/values.h"
21 #include "chrome/browser/chromeos/drive/drive.pb.h"
22 #include "chrome/browser/chromeos/drive/drive_file_system_util.h"
23 #include "chrome/browser/chromeos/drive/drive_test_util.h"
24 #include "chrome/browser/chromeos/drive/drive_webapps_registry.h"
25 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
26 #include "chrome/browser/chromeos/drive/mock_directory_change_observer.h"
27 #include "chrome/browser/chromeos/drive/mock_drive_cache_observer.h"
28 #include "chrome/browser/chromeos/drive/mock_drive_web_apps_registry.h"
29 #include "chrome/browser/chromeos/drive/mock_free_disk_space_getter.h"
30 #include "chrome/browser/google_apis/drive_api_parser.h"
31 #include "chrome/browser/google_apis/drive_uploader.h"
32 #include "chrome/browser/google_apis/mock_drive_service.h"
33 #include "chrome/browser/google_apis/mock_drive_uploader.h"
34 #include "chrome/common/chrome_paths.h"
35 #include "chrome/test/base/testing_profile.h"
36 #include "content/public/browser/browser_thread.h"
37 #include "content/public/test/test_browser_thread.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
41 using ::testing::AnyNumber;
42 using ::testing::AtLeast;
43 using ::testing::Eq;
44 using ::testing::NotNull;
45 using ::testing::Return;
46 using ::testing::StrictMock;
47 using ::testing::_;
49 namespace drive {
50 namespace {
52 // The root directory resource ID for WAPI.
53 // TODO(haruki): Make Drive API equivalent work. http://crbug.com/157114
54 const char kTestRootDirectoryResourceId[] = "folder:testroot";
56 const char kSymLinkToDevNull[] = "/dev/null";
58 const int64 kLotsOfSpace = kMinFreeSpace * 10;
60 struct SearchResultPair {
61 const char* path;
62 const bool is_directory;
65 // Callback to DriveFileSystem::Search used in ContentSearch tests.
66 // Verifies returned vector of results and next feed url.
67 void DriveSearchCallback(
68 MessageLoop* message_loop,
69 const SearchResultPair* expected_results,
70 size_t expected_results_size,
71 const GURL& expected_next_feed,
72 DriveFileError error,
73 const GURL& next_feed,
74 scoped_ptr<std::vector<SearchResultInfo> > results) {
75 ASSERT_TRUE(results.get());
76 ASSERT_EQ(expected_results_size, results->size());
78 for (size_t i = 0; i < results->size(); i++) {
79 EXPECT_EQ(FilePath(expected_results[i].path),
80 results->at(i).path);
81 EXPECT_EQ(expected_results[i].is_directory,
82 results->at(i).is_directory);
85 EXPECT_EQ(expected_next_feed, next_feed);
87 message_loop->Quit();
90 // Action used to set mock expectations for
91 // DriveServiceInterface::GetDocumentEntry().
92 ACTION_P2(MockGetDocumentEntry, status, value) {
93 base::MessageLoopProxy::current()->PostTask(FROM_HERE,
94 base::Bind(arg1, status, base::Passed(value)));
97 // Action used to set mock expectations for
98 // DriveUploaderInterface::UploadExistingFile().
99 ACTION_P4(MockUploadExistingFile,
100 error, drive_path, local_file_path, document_entry) {
101 scoped_ptr<google_apis::DocumentEntry> scoped_document_entry(document_entry);
102 base::MessageLoopProxy::current()->PostTask(FROM_HERE,
103 base::Bind(arg5,
104 error,
105 drive_path,
106 local_file_path,
107 base::Passed(&scoped_document_entry)));
109 const int kUploadId = 123;
110 return kUploadId;
113 // Action used to set mock expectations for
114 // DriveUploaderInterface::UploadNewFile().
115 ACTION(MockUploadNewFile) {
116 scoped_ptr<base::Value> value =
117 google_apis::test_util::LoadJSONFile("gdata/uploaded_file.json");
118 scoped_ptr<google_apis::DocumentEntry> document_entry(
119 google_apis::DocumentEntry::ExtractAndParse(*value));
121 base::MessageLoopProxy::current()->PostTask(FROM_HERE,
122 base::Bind(arg7,
123 google_apis::DRIVE_UPLOAD_OK,
124 arg1,
125 arg2,
126 base::Passed(&document_entry)));
128 const int kUploadId = 123;
129 return kUploadId;
132 // Action used to set mock expectations for
133 // DriveFileSystem::CopyDocument().
134 ACTION_P2(MockCopyDocument, status, value) {
135 base::MessageLoopProxy::current()->PostTask(
136 FROM_HERE,
137 base::Bind(arg2, status, base::Passed(value)));
140 ACTION(MockFailingGetDocuments) {
141 base::MessageLoopProxy::current()->PostTask(
142 FROM_HERE,
143 base::Bind(arg4, google_apis::GDATA_NO_CONNECTION,
144 base::Passed(scoped_ptr<base::Value>())));
147 // Counts the number of files (not directories) in |entries|.
148 int CountFiles(const DriveEntryProtoVector& entries) {
149 int num_files = 0;
150 for (size_t i = 0; i < entries.size(); ++i) {
151 if (!entries[i].file_info().is_directory())
152 ++num_files;
154 return num_files;
157 } // namespace
159 class DriveFileSystemTest : public testing::Test {
160 protected:
161 DriveFileSystemTest()
162 : ui_thread_(content::BrowserThread::UI, &message_loop_),
163 io_thread_(content::BrowserThread::IO),
164 cache_(NULL),
165 file_system_(NULL),
166 mock_drive_service_(NULL),
167 mock_webapps_registry_(NULL),
168 num_callback_invocations_(0),
169 expected_error_(DRIVE_FILE_OK),
170 expected_cache_state_(0),
171 expected_sub_dir_type_(DriveCache::CACHE_TYPE_META),
172 expected_success_(true),
173 expect_outgoing_symlink_(false),
174 root_feed_changestamp_(0) {
177 virtual void SetUp() OVERRIDE {
178 io_thread_.StartIOThread();
180 profile_.reset(new TestingProfile);
182 callback_helper_ = new CallbackHelper;
184 // Allocate and keep a pointer to the mock, and inject it into the
185 // DriveFileSystem object, which will own the mock object.
186 mock_drive_service_ = new StrictMock<google_apis::MockDriveService>;
188 EXPECT_CALL(*mock_drive_service_, Initialize(profile_.get())).Times(1);
190 // Likewise, this will be owned by DriveFileSystem.
191 mock_free_disk_space_checker_ = new StrictMock<MockFreeDiskSpaceGetter>;
192 SetFreeDiskSpaceGetterForTesting(mock_free_disk_space_checker_);
194 scoped_refptr<base::SequencedWorkerPool> pool =
195 content::BrowserThread::GetBlockingPool();
196 blocking_task_runner_ =
197 pool->GetSequencedTaskRunner(pool->GetSequenceToken());
199 cache_ = DriveCache::CreateDriveCacheOnUIThread(
200 DriveCache::GetCacheRootPath(profile_.get()), blocking_task_runner_);
202 mock_uploader_.reset(new StrictMock<google_apis::MockDriveUploader>);
203 mock_webapps_registry_.reset(new StrictMock<MockDriveWebAppsRegistry>);
205 ASSERT_FALSE(file_system_);
206 file_system_ = new DriveFileSystem(profile_.get(),
207 cache_,
208 mock_drive_service_,
209 mock_uploader_.get(),
210 mock_webapps_registry_.get(),
211 blocking_task_runner_);
213 mock_cache_observer_.reset(new StrictMock<MockDriveCacheObserver>);
214 cache_->AddObserver(mock_cache_observer_.get());
216 mock_directory_observer_.reset(new StrictMock<MockDirectoryChangeObserver>);
217 file_system_->AddObserver(mock_directory_observer_.get());
219 file_system_->Initialize();
220 cache_->RequestInitializeOnUIThreadForTesting();
221 google_apis::test_util::RunBlockingPoolTask();
224 virtual void TearDown() OVERRIDE {
225 ASSERT_TRUE(file_system_);
226 EXPECT_CALL(*mock_drive_service_, CancelAll()).Times(1);
227 delete file_system_;
228 file_system_ = NULL;
229 delete mock_drive_service_;
230 mock_drive_service_ = NULL;
231 SetFreeDiskSpaceGetterForTesting(NULL);
232 cache_->DestroyOnUIThread();
233 // The cache destruction requires to post a task to the blocking pool.
234 google_apis::test_util::RunBlockingPoolTask();
236 profile_.reset(NULL);
239 // Loads test json file as root ("/drive") element.
240 void LoadRootFeedDocument(const std::string& filename) {
241 LoadChangeFeed(filename, 0);
244 void LoadChangeFeed(const std::string& filename,
245 int largest_changestamp) {
246 test_util::LoadChangeFeed(filename,
247 file_system_,
248 largest_changestamp,
249 root_feed_changestamp_);
250 root_feed_changestamp_++;
253 void AddDirectoryFromFile(const FilePath& directory_path,
254 const std::string& filename) {
255 scoped_ptr<Value> atom = google_apis::test_util::LoadJSONFile(filename);
256 ASSERT_TRUE(atom.get());
257 ASSERT_TRUE(atom->GetType() == Value::TYPE_DICTIONARY);
259 DictionaryValue* dict_value = NULL;
260 Value* entry_value = NULL;
261 ASSERT_TRUE(atom->GetAsDictionary(&dict_value));
262 ASSERT_TRUE(dict_value->Get("entry", &entry_value));
264 DictionaryValue* entry_dict = NULL;
265 ASSERT_TRUE(entry_value->GetAsDictionary(&entry_dict));
267 // Tweak entry title to match the last segment of the directory path
268 // (new directory name).
269 std::vector<FilePath::StringType> dir_parts;
270 directory_path.GetComponents(&dir_parts);
271 entry_dict->SetString("title.$t", dir_parts[dir_parts.size() - 1]);
273 DriveFileError error;
274 DriveFileSystem::CreateDirectoryParams params(directory_path,
275 directory_path,
276 false, // is_exclusive
277 false, // is_recursive
278 base::Bind(&test_util::CopyErrorCodeFromFileOperationCallback, &error));
279 file_system_->AddNewDirectory(
280 params, google_apis::HTTP_SUCCESS, atom.Pass());
281 google_apis::test_util::RunBlockingPoolTask();
282 EXPECT_EQ(DRIVE_FILE_OK, error);
285 bool RemoveEntry(const FilePath& file_path) {
286 DriveFileError error;
287 EXPECT_CALL(*mock_drive_service_, DeleteDocument(_, _)).Times(AnyNumber());
288 file_system_->Remove(
289 file_path, false,
290 base::Bind(&test_util::CopyErrorCodeFromFileOperationCallback, &error));
292 google_apis::test_util::RunBlockingPoolTask();
293 return error == DRIVE_FILE_OK;
296 FilePath GetCachePathForFile(const std::string& resource_id,
297 const std::string& md5) {
298 return cache_->GetCacheFilePath(resource_id,
299 md5,
300 DriveCache::CACHE_TYPE_TMP,
301 DriveCache::CACHED_FILE_FROM_SERVER);
304 // Gets entry info by path synchronously.
305 scoped_ptr<DriveEntryProto> GetEntryInfoByPathSync(
306 const FilePath& file_path) {
307 file_system_->GetEntryInfoByPath(
308 file_path,
309 base::Bind(&CallbackHelper::GetEntryInfoCallback,
310 callback_helper_.get()));
311 google_apis::test_util::RunBlockingPoolTask();
313 return callback_helper_->entry_proto_.Pass();
316 // Gets directory info by path synchronously.
317 scoped_ptr<DriveEntryProtoVector> ReadDirectoryByPathSync(
318 const FilePath& file_path) {
319 file_system_->ReadDirectoryByPath(
320 file_path,
321 base::Bind(&CallbackHelper::ReadDirectoryCallback,
322 callback_helper_.get()));
323 google_apis::test_util::RunBlockingPoolTask();
325 return callback_helper_->directory_entries_.Pass();
328 // Returns true if an entry exists at |file_path|.
329 bool EntryExists(const FilePath& file_path) {
330 return GetEntryInfoByPathSync(file_path).get();
334 // Gets the resource ID of |file_path|. Returns an empty string if not found.
335 std::string GetResourceIdByPath(const FilePath& file_path) {
336 scoped_ptr<DriveEntryProto> entry_proto =
337 GetEntryInfoByPathSync(file_path);
338 if (entry_proto.get())
339 return entry_proto->resource_id();
340 else
341 return "";
344 // Helper function to call GetCacheEntry from origin thread.
345 bool GetCacheEntryFromOriginThread(const std::string& resource_id,
346 const std::string& md5,
347 DriveCacheEntry* cache_entry) {
348 bool result = false;
349 blocking_task_runner_->PostTask(
350 FROM_HERE,
351 base::Bind(&DriveFileSystemTest::GetCacheEntryFromOriginThreadInternal,
352 base::Unretained(this),
353 resource_id,
354 md5,
355 cache_entry,
356 &result));
357 google_apis::test_util::RunBlockingPoolTask();
358 return result;
361 // Used to implement GetCacheEntry.
362 void GetCacheEntryFromOriginThreadInternal(
363 const std::string& resource_id,
364 const std::string& md5,
365 DriveCacheEntry* cache_entry,
366 bool* result) {
367 *result = cache_->GetCacheEntry(resource_id, md5, cache_entry);
370 // Returns true if the cache entry exists for the given resource ID and MD5.
371 bool CacheEntryExists(const std::string& resource_id,
372 const std::string& md5) {
373 DriveCacheEntry cache_entry;
374 return GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry);
377 // Returns true if the cache file exists for the given resource ID and MD5.
378 bool CacheFileExists(const std::string& resource_id,
379 const std::string& md5) {
380 const FilePath file_path = cache_->GetCacheFilePath(
381 resource_id,
382 md5,
383 DriveCache::CACHE_TYPE_TMP,
384 DriveCache::CACHED_FILE_FROM_SERVER);
385 return file_util::PathExists(file_path);
388 void TestStoreToCache(
389 const std::string& resource_id,
390 const std::string& md5,
391 const FilePath& source_path,
392 DriveFileError expected_error,
393 int expected_cache_state,
394 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
395 expected_error_ = expected_error;
396 expected_cache_state_ = expected_cache_state;
397 expected_sub_dir_type_ = expected_sub_dir_type;
399 cache_->StoreOnUIThread(
400 resource_id, md5, source_path,
401 DriveCache::FILE_OPERATION_COPY,
402 base::Bind(&DriveFileSystemTest::VerifyCacheFileState,
403 base::Unretained(this)));
405 google_apis::test_util::RunBlockingPoolTask();
408 void TestPin(
409 const std::string& resource_id,
410 const std::string& md5,
411 DriveFileError expected_error,
412 int expected_cache_state,
413 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
414 expected_error_ = expected_error;
415 expected_cache_state_ = expected_cache_state;
416 expected_sub_dir_type_ = expected_sub_dir_type;
418 cache_->PinOnUIThread(
419 resource_id, md5,
420 base::Bind(&DriveFileSystemTest::VerifyCacheFileState,
421 base::Unretained(this)));
423 google_apis::test_util::RunBlockingPoolTask();
426 void TestMarkDirty(
427 const std::string& resource_id,
428 const std::string& md5,
429 DriveFileError expected_error,
430 int expected_cache_state,
431 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
432 expected_error_ = expected_error;
433 expected_cache_state_ = expected_cache_state;
434 expected_sub_dir_type_ = expected_sub_dir_type;
435 expect_outgoing_symlink_ = false;
437 cache_->MarkDirtyOnUIThread(
438 resource_id,
439 md5,
440 base::Bind(&DriveFileSystemTest::VerifyMarkDirty,
441 base::Unretained(this),
442 resource_id,
443 md5));
445 google_apis::test_util::RunBlockingPoolTask();
448 void VerifyMarkDirty(const std::string& resource_id,
449 const std::string& md5,
450 DriveFileError error,
451 const FilePath& cache_file_path) {
452 VerifyCacheFileState(error, resource_id, md5);
454 // Verify filename of |cache_file_path|.
455 if (error == DRIVE_FILE_OK) {
456 FilePath base_name = cache_file_path.BaseName();
457 EXPECT_EQ(util::EscapeCacheFileName(resource_id) +
458 FilePath::kExtensionSeparator +
459 "local",
460 base_name.value());
461 } else {
462 EXPECT_TRUE(cache_file_path.empty());
466 void TestCommitDirty(
467 const std::string& resource_id,
468 const std::string& md5,
469 DriveFileError expected_error,
470 int expected_cache_state,
471 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
472 expected_error_ = expected_error;
473 expected_cache_state_ = expected_cache_state;
474 expected_sub_dir_type_ = expected_sub_dir_type;
475 expect_outgoing_symlink_ = true;
477 cache_->CommitDirtyOnUIThread(
478 resource_id, md5,
479 base::Bind(&DriveFileSystemTest::VerifyCacheFileState,
480 base::Unretained(this)));
482 google_apis::test_util::RunBlockingPoolTask();
485 // Verify the file identified by |resource_id| and |md5| is in the expected
486 // cache state after |OpenFile|, that is, marked dirty and has no outgoing
487 // symlink, etc.
488 void VerifyCacheStateAfterOpenFile(DriveFileError error,
489 const std::string& resource_id,
490 const std::string& md5,
491 const FilePath& cache_file_path) {
492 expected_error_ = DRIVE_FILE_OK;
493 expected_cache_state_ = (test_util::TEST_CACHE_STATE_PRESENT |
494 test_util::TEST_CACHE_STATE_DIRTY |
495 test_util::TEST_CACHE_STATE_PERSISTENT);
496 expected_sub_dir_type_ = DriveCache::CACHE_TYPE_PERSISTENT;
497 expect_outgoing_symlink_ = false;
498 VerifyMarkDirty(resource_id, md5, error, cache_file_path);
501 // Verify the file identified by |resource_id| and |md5| is in the expected
502 // cache state after |CloseFile|, that is, marked dirty and has an outgoing
503 // symlink, etc.
504 void VerifyCacheStateAfterCloseFile(DriveFileError error,
505 const std::string& resource_id,
506 const std::string& md5) {
507 expected_error_ = DRIVE_FILE_OK;
508 expected_cache_state_ = (test_util::TEST_CACHE_STATE_PRESENT |
509 test_util::TEST_CACHE_STATE_DIRTY |
510 test_util::TEST_CACHE_STATE_PERSISTENT);
511 expected_sub_dir_type_ = DriveCache::CACHE_TYPE_PERSISTENT;
512 expect_outgoing_symlink_ = true;
513 VerifyCacheFileState(error, resource_id, md5);
516 void VerifyCacheFileState(DriveFileError error,
517 const std::string& resource_id,
518 const std::string& md5) {
519 ++num_callback_invocations_;
521 EXPECT_EQ(expected_error_, error);
523 // Verify cache map.
524 DriveCacheEntry cache_entry;
525 const bool cache_entry_found =
526 GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry);
527 if (test_util::ToCacheEntry(expected_cache_state_).is_present() ||
528 test_util::ToCacheEntry(expected_cache_state_).is_pinned()) {
529 ASSERT_TRUE(cache_entry_found);
530 EXPECT_TRUE(test_util::CacheStatesEqual(
531 test_util::ToCacheEntry(expected_cache_state_),
532 cache_entry));
533 EXPECT_EQ(expected_sub_dir_type_,
534 DriveCache::GetSubDirectoryType(cache_entry));
535 } else {
536 EXPECT_FALSE(cache_entry_found);
539 // Verify actual cache file.
540 FilePath dest_path = cache_->GetCacheFilePath(
541 resource_id,
542 md5,
543 test_util::ToCacheEntry(expected_cache_state_).is_pinned() ||
544 test_util::ToCacheEntry(expected_cache_state_).is_dirty() ?
545 DriveCache::CACHE_TYPE_PERSISTENT :
546 DriveCache::CACHE_TYPE_TMP,
547 test_util::ToCacheEntry(expected_cache_state_).is_dirty() ?
548 DriveCache::CACHED_FILE_LOCALLY_MODIFIED :
549 DriveCache::CACHED_FILE_FROM_SERVER);
550 bool exists = file_util::PathExists(dest_path);
551 if (test_util::ToCacheEntry(expected_cache_state_).is_present())
552 EXPECT_TRUE(exists);
553 else
554 EXPECT_FALSE(exists);
556 // Verify symlink in pinned dir.
557 FilePath symlink_path = cache_->GetCacheFilePath(
558 resource_id,
559 std::string(),
560 DriveCache::CACHE_TYPE_PINNED,
561 DriveCache::CACHED_FILE_FROM_SERVER);
562 // Check that pin symlink exists, without dereferencing to target path.
563 exists = file_util::IsLink(symlink_path);
564 if (test_util::ToCacheEntry(expected_cache_state_).is_pinned()) {
565 EXPECT_TRUE(exists);
566 FilePath target_path;
567 EXPECT_TRUE(file_util::ReadSymbolicLink(symlink_path, &target_path));
568 if (test_util::ToCacheEntry(expected_cache_state_).is_present())
569 EXPECT_EQ(dest_path, target_path);
570 else
571 EXPECT_EQ(kSymLinkToDevNull, target_path.value());
572 } else {
573 EXPECT_FALSE(exists);
576 // Verify symlink in outgoing dir.
577 symlink_path = cache_->GetCacheFilePath(
578 resource_id,
579 std::string(),
580 DriveCache::CACHE_TYPE_OUTGOING,
581 DriveCache::CACHED_FILE_FROM_SERVER);
582 // Check that outgoing symlink exists, without dereferencing to target path.
583 exists = file_util::IsLink(symlink_path);
584 if (expect_outgoing_symlink_ &&
585 test_util::ToCacheEntry(expected_cache_state_).is_dirty()) {
586 EXPECT_TRUE(exists);
587 FilePath target_path;
588 EXPECT_TRUE(file_util::ReadSymbolicLink(symlink_path, &target_path));
589 EXPECT_TRUE(target_path.value() != kSymLinkToDevNull);
590 if (test_util::ToCacheEntry(expected_cache_state_).is_present())
591 EXPECT_EQ(dest_path, target_path);
592 } else {
593 EXPECT_FALSE(exists);
597 void SetExpectationsForGetDocumentEntry(scoped_ptr<base::Value>* document,
598 const std::string& resource_id) {
599 EXPECT_CALL(*mock_drive_service_, GetDocumentEntry(resource_id, _))
600 .WillOnce(MockGetDocumentEntry(google_apis::HTTP_SUCCESS, document));
603 // Loads serialized proto file from GCache, and makes sure the root
604 // filesystem has a root at 'drive'
605 bool TestLoadMetadataFromCache() {
606 DriveFileError error = DRIVE_FILE_ERROR_FAILED;
607 file_system_->LoadRootFeedFromCacheForTesting(
608 base::Bind(&test_util::CopyErrorCodeFromFileOperationCallback, &error));
609 google_apis::test_util::RunBlockingPoolTask();
610 return error == DRIVE_FILE_OK;
613 // Flag for specifying the timestamp of the test filesystem cache.
614 enum SaveTestFileSystemParam {
615 USE_OLD_TIMESTAMP,
616 USE_SERVER_TIMESTAMP,
619 // Creates a proto file representing a filesystem with directories:
620 // drive, drive/Dir1, drive/Dir1/SubDir2
621 // and files
622 // drive/File1, drive/Dir1/File2, drive/Dir1/SubDir2/File3.
623 // If |use_up_to_date_timestamp| is true, sets the changestamp to 654321,
624 // equal to that of "account_metadata.json" test data, indicating the cache is
625 // holding the latest file system info.
626 void SaveTestFileSystem(SaveTestFileSystemParam param) {
627 DriveRootDirectoryProto root;
628 root.set_version(kProtoVersion);
629 root.set_largest_changestamp(param == USE_SERVER_TIMESTAMP ? 654321 : 1);
630 DriveDirectoryProto* root_dir = root.mutable_drive_directory();
631 DriveEntryProto* dir_base = root_dir->mutable_drive_entry();
632 PlatformFileInfoProto* platform_info = dir_base->mutable_file_info();
633 dir_base->set_title("drive");
634 dir_base->set_resource_id(kTestRootDirectoryResourceId);
635 dir_base->set_upload_url("http://resumable-create-media/1");
636 platform_info->set_is_directory(true);
638 // drive/File1
639 DriveEntryProto* file = root_dir->add_child_files();
640 file->set_title("File1");
641 file->set_resource_id("resource_id:File1");
642 file->set_upload_url("http://resumable-edit-media/1");
643 file->mutable_file_specific_info()->set_file_md5("md5");
644 platform_info = file->mutable_file_info();
645 platform_info->set_is_directory(false);
646 platform_info->set_size(1048576);
648 // drive/Dir1
649 DriveDirectoryProto* dir1 = root_dir->add_child_directories();
650 dir_base = dir1->mutable_drive_entry();
651 dir_base->set_title("Dir1");
652 dir_base->set_resource_id("resource_id:Dir1");
653 dir_base->set_upload_url("http://resumable-create-media/2");
654 platform_info = dir_base->mutable_file_info();
655 platform_info->set_is_directory(true);
657 // drive/Dir1/File2
658 file = dir1->add_child_files();
659 file->set_title("File2");
660 file->set_resource_id("resource_id:File2");
661 file->set_upload_url("http://resumable-edit-media/2");
662 file->mutable_file_specific_info()->set_file_md5("md5");
663 platform_info = file->mutable_file_info();
664 platform_info->set_is_directory(false);
665 platform_info->set_size(555);
667 // drive/Dir1/SubDir2
668 DriveDirectoryProto* dir2 = dir1->add_child_directories();
669 dir_base = dir2->mutable_drive_entry();
670 dir_base->set_title("SubDir2");
671 dir_base->set_resource_id("resource_id:SubDir2");
672 dir_base->set_upload_url("http://resumable-create-media/3");
673 platform_info = dir_base->mutable_file_info();
674 platform_info->set_is_directory(true);
676 // drive/Dir1/SubDir2/File3
677 file = dir2->add_child_files();
678 file->set_title("File3");
679 file->set_resource_id("resource_id:File3");
680 file->set_upload_url("http://resumable-edit-media/3");
681 file->mutable_file_specific_info()->set_file_md5("md5");
682 platform_info = file->mutable_file_info();
683 platform_info->set_is_directory(false);
684 platform_info->set_size(12345);
686 // Write this proto out to GCache/vi/meta/file_system.pb
687 std::string serialized_proto;
688 ASSERT_TRUE(root.SerializeToString(&serialized_proto));
689 ASSERT_TRUE(!serialized_proto.empty());
691 FilePath cache_dir_path = profile_->GetPath().Append(
692 FILE_PATH_LITERAL("GCache/v1/meta/"));
693 ASSERT_TRUE(file_util::CreateDirectory(cache_dir_path));
694 const int file_size = static_cast<int>(serialized_proto.length());
695 ASSERT_EQ(file_util::WriteFile(cache_dir_path.Append("file_system.pb"),
696 serialized_proto.data(), file_size), file_size);
699 // Verifies that |file_path| is a valid JSON file for the hosted document
700 // associated with |entry| (i.e. |url| and |resource_id| match).
701 void VerifyHostedDocumentJSONFile(const DriveEntryProto& entry_proto,
702 const FilePath& file_path) {
703 std::string error;
704 JSONFileValueSerializer serializer(file_path);
705 scoped_ptr<Value> value(serializer.Deserialize(NULL, &error));
706 ASSERT_TRUE(value.get()) << "Parse error " << file_path.value()
707 << ": " << error;
708 DictionaryValue* dict_value = NULL;
709 ASSERT_TRUE(value->GetAsDictionary(&dict_value));
711 std::string edit_url, resource_id;
712 EXPECT_TRUE(dict_value->GetString("url", &edit_url));
713 EXPECT_TRUE(dict_value->GetString("resource_id", &resource_id));
715 EXPECT_EQ(entry_proto.file_specific_info().alternate_url(),
716 edit_url);
717 EXPECT_EQ(entry_proto.resource_id(), resource_id);
720 // This is used as a helper for registering callbacks that need to be
721 // RefCountedThreadSafe, and a place where we can fetch results from various
722 // operations.
723 class CallbackHelper
724 : public base::RefCountedThreadSafe<CallbackHelper> {
725 public:
726 CallbackHelper()
727 : last_error_(DRIVE_FILE_OK),
728 quota_bytes_total_(0),
729 quota_bytes_used_(0),
730 entry_proto_(NULL) {}
732 virtual void GetFileCallback(DriveFileError error,
733 const FilePath& file_path,
734 const std::string& mime_type,
735 DriveFileType file_type) {
736 last_error_ = error;
737 download_path_ = file_path;
738 mime_type_ = mime_type;
739 file_type_ = file_type;
742 virtual void FileOperationCallback(DriveFileError error) {
743 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
745 last_error_ = error;
748 virtual void GetAvailableSpaceCallback(DriveFileError error,
749 int64 bytes_total,
750 int64 bytes_used) {
751 last_error_ = error;
752 quota_bytes_total_ = bytes_total;
753 quota_bytes_used_ = bytes_used;
756 virtual void OpenFileCallback(DriveFileError error,
757 const FilePath& file_path) {
758 last_error_ = error;
759 opened_file_path_ = file_path;
760 MessageLoop::current()->Quit();
763 virtual void CloseFileCallback(DriveFileError error) {
764 last_error_ = error;
765 MessageLoop::current()->Quit();
768 virtual void GetEntryInfoCallback(
769 DriveFileError error,
770 scoped_ptr<DriveEntryProto> entry_proto) {
771 last_error_ = error;
772 entry_proto_ = entry_proto.Pass();
775 virtual void ReadDirectoryCallback(
776 DriveFileError error,
777 bool /* hide_hosted_documents */,
778 scoped_ptr<DriveEntryProtoVector> entries) {
779 last_error_ = error;
780 directory_entries_ = entries.Pass();
783 DriveFileError last_error_;
784 FilePath download_path_;
785 FilePath opened_file_path_;
786 std::string mime_type_;
787 DriveFileType file_type_;
788 int64 quota_bytes_total_;
789 int64 quota_bytes_used_;
790 scoped_ptr<DriveEntryProto> entry_proto_;
791 scoped_ptr<DriveEntryProtoVector> directory_entries_;
793 protected:
794 virtual ~CallbackHelper() {}
796 private:
797 friend class base::RefCountedThreadSafe<CallbackHelper>;
800 // Copy the result from FindFirstMissingParentDirectory().
801 static void CopyResultFromFindFirstMissingParentDirectory(
802 DriveFileSystem::FindFirstMissingParentDirectoryResult* out_result,
803 const DriveFileSystem::FindFirstMissingParentDirectoryResult& result) {
804 DCHECK(out_result);
805 *out_result = result;
808 MessageLoopForUI message_loop_;
809 // The order of the test threads is important, do not change the order.
810 // See also content/browser/browser_thread_impl.cc.
811 content::TestBrowserThread ui_thread_;
812 content::TestBrowserThread io_thread_;
813 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
814 scoped_ptr<TestingProfile> profile_;
815 scoped_refptr<CallbackHelper> callback_helper_;
816 DriveCache* cache_;
817 scoped_ptr<StrictMock<google_apis::MockDriveUploader> > mock_uploader_;
818 DriveFileSystem* file_system_;
819 StrictMock<google_apis::MockDriveService>* mock_drive_service_;
820 scoped_ptr<StrictMock<MockDriveWebAppsRegistry> > mock_webapps_registry_;
821 StrictMock<MockFreeDiskSpaceGetter>* mock_free_disk_space_checker_;
822 scoped_ptr<StrictMock<MockDriveCacheObserver> > mock_cache_observer_;
823 scoped_ptr<StrictMock<MockDirectoryChangeObserver> > mock_directory_observer_;
825 int num_callback_invocations_;
826 DriveFileError expected_error_;
827 int expected_cache_state_;
828 DriveCache::CacheSubDirectoryType expected_sub_dir_type_;
829 bool expected_success_;
830 bool expect_outgoing_symlink_;
831 std::string expected_file_extension_;
832 int root_feed_changestamp_;
835 void AsyncInitializationCallback(
836 int* counter,
837 int expected_counter,
838 const FilePath& expected_file_path,
839 MessageLoop* message_loop,
840 DriveFileError error,
841 scoped_ptr<DriveEntryProto> entry_proto) {
842 ASSERT_EQ(DRIVE_FILE_OK, error);
843 ASSERT_TRUE(entry_proto.get());
844 ASSERT_TRUE(entry_proto->file_info().is_directory());
845 EXPECT_EQ(expected_file_path.value(), entry_proto->base_name());
847 (*counter)++;
848 if (*counter >= expected_counter)
849 message_loop->Quit();
852 TEST_F(DriveFileSystemTest, DuplicatedAsyncInitialization) {
853 int counter = 0;
854 GetEntryInfoCallback callback = base::Bind(
855 &AsyncInitializationCallback,
856 &counter,
858 FilePath(FILE_PATH_LITERAL("drive")),
859 &message_loop_);
861 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
862 EXPECT_CALL(*mock_drive_service_,
863 GetDocuments(Eq(GURL()), _, _, _, _)).Times(1);
865 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
867 file_system_->GetEntryInfoByPath(
868 FilePath(FILE_PATH_LITERAL("drive")), callback);
869 file_system_->GetEntryInfoByPath(
870 FilePath(FILE_PATH_LITERAL("drive")), callback);
871 message_loop_.Run(); // Wait to get our result
872 EXPECT_EQ(2, counter);
875 TEST_F(DriveFileSystemTest, SearchRootDirectory) {
876 LoadRootFeedDocument("gdata/root_feed.json");
878 const FilePath kFilePath = FilePath(FILE_PATH_LITERAL("drive"));
879 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(
880 FilePath(FILE_PATH_LITERAL(kFilePath)));
881 ASSERT_TRUE(entry.get());
882 // We get kWAPIRootDirectoryResourceId instead of kTestRootDirectoryResourceId
883 // here, as the root ID is set in DriveFeedLoader::UpdateFromFeed().
884 EXPECT_EQ(kWAPIRootDirectoryResourceId, entry->resource_id());
887 TEST_F(DriveFileSystemTest, SearchExistingFile) {
888 LoadRootFeedDocument("gdata/root_feed.json");
890 const FilePath kFilePath = FilePath(
891 FILE_PATH_LITERAL("drive/File 1.txt"));
892 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
893 ASSERT_TRUE(entry.get());
894 EXPECT_EQ("file:2_file_resource_id", entry->resource_id());
897 TEST_F(DriveFileSystemTest, SearchExistingDocument) {
898 LoadRootFeedDocument("gdata/root_feed.json");
900 const FilePath kFilePath = FilePath(
901 FILE_PATH_LITERAL("drive/Document 1.gdoc"));
902 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
903 ASSERT_TRUE(entry.get());
904 EXPECT_EQ("document:5_document_resource_id", entry->resource_id());
907 TEST_F(DriveFileSystemTest, SearchNonExistingFile) {
908 LoadRootFeedDocument("gdata/root_feed.json");
910 const FilePath kFilePath = FilePath(
911 FILE_PATH_LITERAL("drive/nonexisting.file"));
912 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
913 ASSERT_FALSE(entry.get());
916 TEST_F(DriveFileSystemTest, SearchEncodedFileNames) {
917 LoadRootFeedDocument("gdata/root_feed.json");
919 const FilePath kFilePath1 = FilePath(
920 FILE_PATH_LITERAL("drive/Slash / in file 1.txt"));
921 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath1);
922 ASSERT_FALSE(entry.get());
924 const FilePath kFilePath2 = FilePath::FromUTF8Unsafe(
925 "drive/Slash \xE2\x88\x95 in file 1.txt");
926 entry = GetEntryInfoByPathSync(kFilePath2);
927 ASSERT_TRUE(entry.get());
928 EXPECT_EQ("file:slash_file_resource_id", entry->resource_id());
930 const FilePath kFilePath3 = FilePath::FromUTF8Unsafe(
931 "drive/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt");
932 entry = GetEntryInfoByPathSync(kFilePath3);
933 ASSERT_TRUE(entry.get());
934 EXPECT_EQ("file:slash_subdir_file", entry->resource_id());
937 TEST_F(DriveFileSystemTest, SearchEncodedFileNamesLoadingRoot) {
938 LoadRootFeedDocument("gdata/root_feed.json");
940 const FilePath kFilePath1 = FilePath(
941 FILE_PATH_LITERAL("drive/Slash / in file 1.txt"));
942 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath1);
943 ASSERT_FALSE(entry.get());
945 const FilePath kFilePath2 = FilePath::FromUTF8Unsafe(
946 "drive/Slash \xE2\x88\x95 in file 1.txt");
947 entry = GetEntryInfoByPathSync(kFilePath2);
948 ASSERT_TRUE(entry.get());
949 EXPECT_EQ("file:slash_file_resource_id", entry->resource_id());
951 const FilePath kFilePath3 = FilePath::FromUTF8Unsafe(
952 "drive/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt");
953 entry = GetEntryInfoByPathSync(kFilePath3);
954 ASSERT_TRUE(entry.get());
955 EXPECT_EQ("file:slash_subdir_file", entry->resource_id());
958 TEST_F(DriveFileSystemTest, SearchDuplicateNames) {
959 LoadRootFeedDocument("gdata/root_feed.json");
961 const FilePath kFilePath1 = FilePath(
962 FILE_PATH_LITERAL("drive/Duplicate Name.txt"));
963 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath1);
964 ASSERT_TRUE(entry.get());
965 EXPECT_EQ("file:3_file_resource_id", entry->resource_id());
967 const FilePath kFilePath2 = FilePath(
968 FILE_PATH_LITERAL("drive/Duplicate Name (2).txt"));
969 entry = GetEntryInfoByPathSync(kFilePath2);
970 ASSERT_TRUE(entry.get());
971 EXPECT_EQ("file:4_file_resource_id", entry->resource_id());
974 TEST_F(DriveFileSystemTest, SearchExistingDirectory) {
975 LoadRootFeedDocument("gdata/root_feed.json");
977 const FilePath kFilePath = FilePath(
978 FILE_PATH_LITERAL("drive/Directory 1"));
979 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
980 ASSERT_TRUE(entry.get());
981 ASSERT_EQ("folder:1_folder_resource_id", entry->resource_id());
984 TEST_F(DriveFileSystemTest, SearchInSubdir) {
985 LoadRootFeedDocument("gdata/root_feed.json");
987 const FilePath kFilePath = FilePath(
988 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
989 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
990 ASSERT_TRUE(entry.get());
991 ASSERT_EQ("file:subdirectory_file_1_id", entry->resource_id());
994 // Check the reconstruction of the directory structure from only the root feed.
995 TEST_F(DriveFileSystemTest, SearchInSubSubdir) {
996 LoadRootFeedDocument("gdata/root_feed.json");
998 const FilePath kFilePath = FilePath(
999 FILE_PATH_LITERAL("drive/Directory 1/Sub Directory Folder/"
1000 "Sub Sub Directory Folder"));
1001 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
1002 ASSERT_TRUE(entry.get());
1003 ASSERT_EQ("folder:sub_sub_directory_folder_id", entry->resource_id());
1006 TEST_F(DriveFileSystemTest, FilePathTests) {
1007 LoadRootFeedDocument("gdata/root_feed.json");
1009 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/File 1.txt"))));
1010 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))));
1011 EXPECT_TRUE(EntryExists(
1012 FilePath(
1013 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"))));
1016 TEST_F(DriveFileSystemTest, ChangeFeed_AddAndDeleteFileInRoot) {
1017 int latest_changelog = 0;
1018 LoadRootFeedDocument("gdata/root_feed.json");
1020 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1021 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(2);
1023 LoadChangeFeed("gdata/delta_file_added_in_root.json", ++latest_changelog);
1024 EXPECT_TRUE(
1025 EntryExists(FilePath(FILE_PATH_LITERAL("drive/Added file.gdoc"))));
1027 LoadChangeFeed("gdata/delta_file_deleted_in_root.json", ++latest_changelog);
1028 EXPECT_FALSE(
1029 EntryExists(FilePath(FILE_PATH_LITERAL("drive/Added file.gdoc"))));
1033 TEST_F(DriveFileSystemTest, ChangeFeed_AddAndDeleteFileFromExistingDirectory) {
1034 int latest_changelog = 0;
1035 LoadRootFeedDocument("gdata/root_feed.json");
1037 EXPECT_TRUE(EntryExists(FilePath(
1038 FILE_PATH_LITERAL("drive/Directory 1"))));
1040 // Add file to an existing directory.
1041 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1042 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1043 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1044 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1045 LoadChangeFeed("gdata/delta_file_added_in_directory.json",
1046 ++latest_changelog);
1047 EXPECT_TRUE(EntryExists(FilePath(
1048 FILE_PATH_LITERAL("drive/Directory 1/Added file.gdoc"))));
1050 // Remove that file from the directory.
1051 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1052 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1053 LoadChangeFeed("gdata/delta_file_deleted_in_directory.json",
1054 ++latest_changelog);
1055 EXPECT_TRUE(EntryExists(FilePath(
1056 FILE_PATH_LITERAL("drive/Directory 1"))));
1057 EXPECT_FALSE(EntryExists(FilePath(
1058 FILE_PATH_LITERAL("drive/Directory 1/Added file.gdoc"))));
1061 TEST_F(DriveFileSystemTest, ChangeFeed_AddFileToNewDirectory) {
1062 int latest_changelog = 0;
1063 LoadRootFeedDocument("gdata/root_feed.json");
1064 // Add file to a new directory.
1065 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1066 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1067 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1068 Eq(FilePath(FILE_PATH_LITERAL("drive/New Directory"))))).Times(1);
1070 LoadChangeFeed("gdata/delta_file_added_in_new_directory.json",
1071 ++latest_changelog);
1073 EXPECT_TRUE(EntryExists(FilePath(
1074 FILE_PATH_LITERAL("drive/New Directory"))));
1075 EXPECT_TRUE(EntryExists(FilePath(
1076 FILE_PATH_LITERAL("drive/New Directory/File in new dir.gdoc"))));
1079 TEST_F(DriveFileSystemTest, ChangeFeed_AddFileToNewButDeletedDirectory) {
1080 int latest_changelog = 0;
1081 LoadRootFeedDocument("gdata/root_feed.json");
1083 // This feed contains thw following updates:
1084 // 1) A new PDF file is added to a new directory
1085 // 2) but the new directory is marked "deleted" (i.e. moved to Trash)
1086 // Hence, the PDF file should be just ignored.
1087 LoadChangeFeed("gdata/delta_file_added_in_new_but_deleted_directory.json",
1088 ++latest_changelog);
1091 TEST_F(DriveFileSystemTest, ChangeFeed_DirectoryMovedFromRootToDirectory) {
1092 int latest_changelog = 0;
1093 LoadRootFeedDocument("gdata/root_feed.json");
1095 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1096 "drive/Directory 2"))));
1097 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1098 "drive/Directory 1"))));
1099 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1100 "drive/Directory 1/SubDirectory File 1.txt"))));
1101 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1102 "drive/Directory 1/Sub Directory Folder"))));
1103 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1104 "drive/Directory 1/Sub Directory Folder/Sub Sub Directory Folder"))));
1106 // This will move "Directory 1" from "drive/" to "drive/Directory 2/".
1107 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1108 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1109 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1110 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1111 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1112 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 2"))))).Times(1);
1113 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1114 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 2/Directory 1")))))
1115 .Times(1);
1116 LoadChangeFeed("gdata/delta_dir_moved_from_root_to_directory.json",
1117 ++latest_changelog);
1119 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1120 "drive/Directory 2"))));
1121 EXPECT_FALSE(EntryExists(FilePath(FILE_PATH_LITERAL(
1122 "drive/Directory 1"))));
1123 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1124 "drive/Directory 2/Directory 1"))));
1125 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1126 "drive/Directory 2/Directory 1/SubDirectory File 1.txt"))));
1127 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1128 "drive/Directory 2/Directory 1/Sub Directory Folder"))));
1129 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1130 "drive/Directory 2/Directory 1/Sub Directory Folder/"
1131 "Sub Sub Directory Folder"))));
1134 TEST_F(DriveFileSystemTest, ChangeFeed_FileMovedFromDirectoryToRoot) {
1135 int latest_changelog = 0;
1136 LoadRootFeedDocument("gdata/root_feed.json");
1138 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1139 "drive/Directory 1"))));
1140 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1141 "drive/Directory 1/Sub Directory Folder"))));
1142 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1143 "drive/Directory 1/Sub Directory Folder/Sub Sub Directory Folder"))));
1144 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1145 "drive/Directory 1/SubDirectory File 1.txt"))));
1147 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1148 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1149 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1150 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1151 LoadChangeFeed("gdata/delta_file_moved_from_directory_to_root.json",
1152 ++latest_changelog);
1154 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1155 "drive/Directory 1"))));
1156 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1157 "drive/Directory 1/Sub Directory Folder"))));
1158 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1159 "drive/Directory 1/Sub Directory Folder/Sub Sub Directory Folder"))));
1160 EXPECT_FALSE(EntryExists(FilePath(FILE_PATH_LITERAL(
1161 "drive/Directory 1/SubDirectory File 1.txt"))));
1162 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1163 "drive/SubDirectory File 1.txt"))));
1166 TEST_F(DriveFileSystemTest, ChangeFeed_FileRenamedInDirectory) {
1167 int latest_changelog = 0;
1168 LoadRootFeedDocument("gdata/root_feed.json");
1170 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1171 "drive/Directory 1"))));
1172 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1173 "drive/Directory 1/SubDirectory File 1.txt"))));
1175 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1176 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1177 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1178 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1179 LoadChangeFeed("gdata/delta_file_renamed_in_directory.json",
1180 ++latest_changelog);
1182 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1183 "drive/Directory 1"))));
1184 EXPECT_FALSE(EntryExists(FilePath(FILE_PATH_LITERAL(
1185 "drive/Directory 1/SubDirectory File 1.txt"))));
1186 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1187 "drive/Directory 1/New SubDirectory File 1.txt"))));
1190 TEST_F(DriveFileSystemTest, CachedFeedLoading) {
1191 SaveTestFileSystem(USE_OLD_TIMESTAMP);
1192 ASSERT_TRUE(TestLoadMetadataFromCache());
1194 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/File1"))));
1195 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Dir1"))));
1196 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Dir1/File2"))));
1197 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Dir1/SubDir2"))));
1198 EXPECT_TRUE(EntryExists(
1199 FilePath(FILE_PATH_LITERAL("drive/Dir1/SubDir2/File3"))));
1202 TEST_F(DriveFileSystemTest, CachedFeedLoadingThenServerFeedLoading) {
1203 SaveTestFileSystem(USE_SERVER_TIMESTAMP);
1205 // SaveTestFileSystem and "account_metadata.json" have the same changestamp,
1206 // so no request for new feeds (i.e., call to GetDocuments) should happen.
1207 // Account metadata is already set up in MockDriveService's constructor.
1208 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
1209 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
1210 EXPECT_CALL(*mock_drive_service_, GetDocuments(_, _, _, _, _)).Times(0);
1212 // Kicks loading of cached file system and query for server update.
1213 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/File1"))));
1215 // Since the file system has verified that it holds the latest snapshot,
1216 // it should change its state to INITIALIZED, which admits periodic refresh.
1217 // To test it, call CheckForUpdates and verify it does try to check updates.
1218 mock_drive_service_->set_account_metadata(
1219 google_apis::test_util::LoadJSONFile(
1220 "gdata/account_metadata.json").release());
1221 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
1222 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
1224 file_system_->CheckForUpdates();
1225 google_apis::test_util::RunBlockingPoolTask();
1228 TEST_F(DriveFileSystemTest, OfflineCachedFeedLoading) {
1229 SaveTestFileSystem(USE_OLD_TIMESTAMP);
1231 // Account metadata is already set up in MockDriveService's constructor.
1232 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
1233 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
1235 // Make GetDocuments fail for simulating offline situation. This will leave
1236 // the file system "loaded from cache, but not synced with server" state.
1237 EXPECT_CALL(*mock_drive_service_, GetDocuments(_, _, _, _, _))
1238 .WillOnce(MockFailingGetDocuments());
1240 // Kicks loading of cached file system and query for server update.
1241 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/File1"))));
1243 // Since the file system has at least succeeded to load cached snapshot,
1244 // the file system should be able to start periodic refresh.
1245 // To test it, call CheckForUpdates and verify it does try to check updates.
1246 mock_drive_service_->set_account_metadata(
1247 google_apis::test_util::LoadJSONFile(
1248 "gdata/account_metadata.json").release());
1249 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
1250 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
1251 EXPECT_CALL(*mock_drive_service_, GetDocuments(_, _, _, _, _)).Times(1);
1253 file_system_->CheckForUpdates();
1254 // Expected value from reading gdata/basic_feed.json.
1255 // See MockDriveService's |feed_data_|.
1256 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_)).Times(2);
1258 google_apis::test_util::RunBlockingPoolTask();
1261 TEST_F(DriveFileSystemTest, TransferFileFromLocalToRemote_RegularFile) {
1262 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
1263 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
1265 LoadRootFeedDocument("gdata/root_feed.json");
1267 // We'll add a file to the Drive root directory.
1268 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1269 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1271 FileOperationCallback callback =
1272 base::Bind(&CallbackHelper::FileOperationCallback,
1273 callback_helper_.get());
1275 // Prepare a local file.
1276 ScopedTempDir temp_dir;
1277 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1278 const FilePath local_src_file_path = temp_dir.path().Append("local.txt");
1279 const std::string kContent = "hello";
1280 file_util::WriteFile(local_src_file_path, kContent.data(), kContent.size());
1282 // Confirm that the remote file does not exist.
1283 const FilePath remote_dest_file_path(FILE_PATH_LITERAL("drive/remote.txt"));
1284 EXPECT_FALSE(EntryExists(remote_dest_file_path));
1286 scoped_ptr<base::Value> value =
1287 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
1288 scoped_ptr<google_apis::DocumentEntry> document_entry(
1289 google_apis::DocumentEntry::ExtractAndParse(*value));
1291 EXPECT_CALL(*mock_uploader_, UploadNewFile(_, _, _, _, _, _, _, _, _))
1292 .WillOnce(MockUploadNewFile());
1294 // Transfer the local file to Drive.
1295 file_system_->TransferFileFromLocalToRemote(
1296 local_src_file_path, remote_dest_file_path, callback);
1297 google_apis::test_util::RunBlockingPoolTask();
1299 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1301 // Now the remote file should exist.
1302 EXPECT_TRUE(EntryExists(remote_dest_file_path));
1305 TEST_F(DriveFileSystemTest, TransferFileFromLocalToRemote_HostedDocument) {
1306 LoadRootFeedDocument("gdata/root_feed.json");
1308 // Prepare a local file, which is a json file of a hosted document, which
1309 // matches "Document 1" in root_feed.json.
1310 ScopedTempDir temp_dir;
1311 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1312 const FilePath local_src_file_path = temp_dir.path().Append("local.gdoc");
1313 const std::string kEditUrl =
1314 "https://3_document_self_link/document:5_document_resource_id";
1315 const std::string kResourceId = "document:5_document_resource_id";
1316 const std::string kContent =
1317 base::StringPrintf("{\"url\": \"%s\", \"resource_id\": \"%s\"}",
1318 kEditUrl.c_str(), kResourceId.c_str());
1319 file_util::WriteFile(local_src_file_path, kContent.data(), kContent.size());
1321 // Confirm that the remote file does not exist.
1322 const FilePath remote_dest_file_path(
1323 FILE_PATH_LITERAL("drive/Directory 1/Document 1.gdoc"));
1324 EXPECT_FALSE(EntryExists(remote_dest_file_path));
1326 // We'll add a file to "Directory 1" directory on Drive.
1327 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1328 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1330 // We'll copy a hosted document using CopyDocument.
1331 // ".gdoc" suffix should be stripped when copying.
1332 scoped_ptr<base::Value> document =
1333 google_apis::test_util::LoadJSONFile("gdata/uploaded_document.json");
1334 EXPECT_CALL(*mock_drive_service_,
1335 CopyDocument(kResourceId,
1336 FILE_PATH_LITERAL("Document 1"),
1338 .WillOnce(MockCopyDocument(google_apis::HTTP_SUCCESS, &document));
1339 // We'll then add the hosted document to the destination directory.
1340 EXPECT_CALL(*mock_drive_service_,
1341 AddResourceToDirectory(_, _, _)).Times(1);
1343 FileOperationCallback callback =
1344 base::Bind(&CallbackHelper::FileOperationCallback,
1345 callback_helper_.get());
1347 // Transfer the local file to Drive.
1348 file_system_->TransferFileFromLocalToRemote(
1349 local_src_file_path, remote_dest_file_path, callback);
1350 google_apis::test_util::RunBlockingPoolTask();
1352 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1354 // Now the remote file should exist.
1355 EXPECT_TRUE(EntryExists(remote_dest_file_path));
1358 TEST_F(DriveFileSystemTest, TransferFileFromRemoteToLocal_RegularFile) {
1359 LoadRootFeedDocument("gdata/root_feed.json");
1361 FileOperationCallback callback =
1362 base::Bind(&CallbackHelper::FileOperationCallback,
1363 callback_helper_.get());
1365 ScopedTempDir temp_dir;
1366 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1367 FilePath local_dest_file_path = temp_dir.path().Append("local_copy.txt");
1369 FilePath remote_src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1370 scoped_ptr<DriveEntryProto> file = GetEntryInfoByPathSync(
1371 remote_src_file_path);
1372 FilePath cache_file = GetCachePathForFile(
1373 file->resource_id(),
1374 file->file_specific_info().file_md5());
1375 const int64 file_size = file->file_info().size();
1377 // Pretend we have enough space.
1378 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
1379 .Times(2).WillRepeatedly(Return(file_size + kMinFreeSpace));
1381 const std::string remote_src_file_data = "Test file data";
1382 mock_drive_service_->set_file_data(new std::string(remote_src_file_data));
1384 // Before Download starts metadata from server will be fetched.
1385 // We will read content url from the result.
1386 scoped_ptr<base::Value> document =
1387 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
1388 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
1390 // The file is obtained with the mock DriveService.
1391 EXPECT_CALL(*mock_drive_service_,
1392 DownloadFile(remote_src_file_path,
1393 cache_file,
1394 GURL("https://file_content_url_changed/"),
1395 _, _))
1396 .Times(1);
1398 file_system_->TransferFileFromRemoteToLocal(
1399 remote_src_file_path, local_dest_file_path, callback);
1400 google_apis::test_util::RunBlockingPoolTask();
1402 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1404 std::string cache_file_data;
1405 EXPECT_TRUE(file_util::ReadFileToString(cache_file, &cache_file_data));
1406 EXPECT_EQ(remote_src_file_data, cache_file_data);
1408 std::string local_dest_file_data;
1409 EXPECT_TRUE(file_util::ReadFileToString(local_dest_file_path,
1410 &local_dest_file_data));
1411 EXPECT_EQ(remote_src_file_data, local_dest_file_data);
1414 TEST_F(DriveFileSystemTest, TransferFileFromRemoteToLocal_HostedDocument) {
1415 LoadRootFeedDocument("gdata/root_feed.json");
1417 FileOperationCallback callback =
1418 base::Bind(&CallbackHelper::FileOperationCallback,
1419 callback_helper_.get());
1421 ScopedTempDir temp_dir;
1422 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1423 FilePath local_dest_file_path = temp_dir.path().Append("local_copy.txt");
1424 FilePath remote_src_file_path(FILE_PATH_LITERAL("drive/Document 1.gdoc"));
1425 file_system_->TransferFileFromRemoteToLocal(
1426 remote_src_file_path, local_dest_file_path, callback);
1427 google_apis::test_util::RunBlockingPoolTask();
1429 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1431 scoped_ptr<DriveEntryProto> entry_proto = GetEntryInfoByPathSync(
1432 remote_src_file_path);
1433 ASSERT_TRUE(entry_proto.get());
1434 VerifyHostedDocumentJSONFile(*entry_proto, local_dest_file_path);
1437 TEST_F(DriveFileSystemTest, CopyNotExistingFile) {
1438 FilePath src_file_path(FILE_PATH_LITERAL("drive/Dummy file.txt"));
1439 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1441 LoadRootFeedDocument("gdata/root_feed.json");
1443 EXPECT_FALSE(EntryExists(src_file_path));
1445 FileOperationCallback callback =
1446 base::Bind(&CallbackHelper::FileOperationCallback,
1447 callback_helper_.get());
1449 file_system_->Copy(src_file_path, dest_file_path, callback);
1450 google_apis::test_util::RunBlockingPoolTask();
1451 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1453 EXPECT_FALSE(EntryExists(src_file_path));
1454 EXPECT_FALSE(EntryExists(dest_file_path));
1457 TEST_F(DriveFileSystemTest, CopyFileToNonExistingDirectory) {
1458 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1459 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Dummy"));
1460 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Dummy/Test.log"));
1462 LoadRootFeedDocument("gdata/root_feed.json");
1464 ASSERT_TRUE(EntryExists(src_file_path));
1465 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1466 src_file_path);
1467 ASSERT_TRUE(src_entry_proto.get());
1468 std::string src_file_path_resource_id =
1469 src_entry_proto->resource_id();
1470 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1472 EXPECT_FALSE(EntryExists(dest_parent_path));
1474 FileOperationCallback callback =
1475 base::Bind(&CallbackHelper::FileOperationCallback,
1476 callback_helper_.get());
1478 file_system_->Move(src_file_path, dest_file_path, callback);
1479 google_apis::test_util::RunBlockingPoolTask();
1480 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1482 EXPECT_TRUE(EntryExists(src_file_path));
1483 EXPECT_FALSE(EntryExists(dest_parent_path));
1484 EXPECT_FALSE(EntryExists(dest_file_path));
1487 // Test the case where the parent of |dest_file_path| is an existing file,
1488 // not a directory.
1489 TEST_F(DriveFileSystemTest, CopyFileToInvalidPath) {
1490 FilePath src_file_path(FILE_PATH_LITERAL("drive/Document 1.gdoc"));
1491 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Duplicate Name.txt"));
1492 FilePath dest_file_path(FILE_PATH_LITERAL(
1493 "drive/Duplicate Name.txt/Document 1.gdoc"));
1495 LoadRootFeedDocument("gdata/root_feed.json");
1497 ASSERT_TRUE(EntryExists(src_file_path));
1498 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1499 src_file_path);
1500 ASSERT_TRUE(src_entry_proto.get());
1501 std::string src_file_resource_id =
1502 src_entry_proto->resource_id();
1503 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1505 ASSERT_TRUE(EntryExists(dest_parent_path));
1506 scoped_ptr<DriveEntryProto> dest_entry_proto = GetEntryInfoByPathSync(
1507 dest_parent_path);
1508 ASSERT_TRUE(dest_entry_proto.get());
1510 FileOperationCallback callback =
1511 base::Bind(&CallbackHelper::FileOperationCallback,
1512 callback_helper_.get());
1514 file_system_->Copy(src_file_path, dest_file_path, callback);
1515 google_apis::test_util::RunBlockingPoolTask();
1516 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_A_DIRECTORY,
1517 callback_helper_->last_error_);
1519 EXPECT_TRUE(EntryExists(src_file_path));
1520 EXPECT_TRUE(EntryExists(src_file_path));
1521 EXPECT_TRUE(EntryExists(dest_parent_path));
1523 EXPECT_FALSE(EntryExists(dest_file_path));
1526 TEST_F(DriveFileSystemTest, RenameFile) {
1527 const FilePath src_file_path(
1528 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1529 const FilePath src_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1530 const FilePath dest_file_path(
1531 FILE_PATH_LITERAL("drive/Directory 1/Test.log"));
1533 LoadRootFeedDocument("gdata/root_feed.json");
1535 ASSERT_TRUE(EntryExists(src_file_path));
1536 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1537 src_file_path);
1538 ASSERT_TRUE(src_entry_proto.get());
1539 std::string src_file_resource_id =
1540 src_entry_proto->resource_id();
1542 EXPECT_CALL(*mock_drive_service_,
1543 RenameResource(GURL(src_entry_proto->edit_url()),
1544 FILE_PATH_LITERAL("Test.log"), _));
1546 FileOperationCallback callback =
1547 base::Bind(&CallbackHelper::FileOperationCallback,
1548 callback_helper_.get());
1550 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1551 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1553 file_system_->Move(src_file_path, dest_file_path, callback);
1554 google_apis::test_util::RunBlockingPoolTask();
1555 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1557 EXPECT_FALSE(EntryExists(src_file_path));
1558 EXPECT_TRUE(EntryExists(dest_file_path));
1559 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1562 TEST_F(DriveFileSystemTest, MoveFileFromRootToSubDirectory) {
1563 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1564 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1565 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Directory 1/Test.log"));
1567 LoadRootFeedDocument("gdata/root_feed.json");
1569 ASSERT_TRUE(EntryExists(src_file_path));
1570 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1571 src_file_path);
1572 ASSERT_TRUE(src_entry_proto.get());
1573 std::string src_file_resource_id =
1574 src_entry_proto->resource_id();
1575 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1577 ASSERT_TRUE(EntryExists(dest_parent_path));
1578 scoped_ptr<DriveEntryProto> dest_parent_proto = GetEntryInfoByPathSync(
1579 dest_parent_path);
1580 ASSERT_TRUE(dest_parent_proto.get());
1581 ASSERT_TRUE(dest_parent_proto->file_info().is_directory());
1582 EXPECT_FALSE(dest_parent_proto->content_url().empty());
1584 EXPECT_CALL(*mock_drive_service_,
1585 RenameResource(GURL(src_entry_proto->edit_url()),
1586 FILE_PATH_LITERAL("Test.log"), _));
1587 EXPECT_CALL(*mock_drive_service_,
1588 AddResourceToDirectory(
1589 GURL(dest_parent_proto->content_url()),
1590 GURL(src_entry_proto->edit_url()), _));
1592 FileOperationCallback callback =
1593 base::Bind(&CallbackHelper::FileOperationCallback,
1594 callback_helper_.get());
1596 // Expect notification for both source and destination directories.
1597 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1598 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1599 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1600 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1602 file_system_->Move(src_file_path, dest_file_path, callback);
1603 google_apis::test_util::RunBlockingPoolTask();
1604 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1606 EXPECT_FALSE(EntryExists(src_file_path));
1607 EXPECT_TRUE(EntryExists(dest_file_path));
1608 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1611 TEST_F(DriveFileSystemTest, MoveFileFromSubDirectoryToRoot) {
1612 FilePath src_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1613 FilePath src_file_path(
1614 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1615 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1617 LoadRootFeedDocument("gdata/root_feed.json");
1619 ASSERT_TRUE(EntryExists(src_file_path));
1620 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1621 src_file_path);
1622 ASSERT_TRUE(src_entry_proto.get());
1623 std::string src_file_resource_id =
1624 src_entry_proto->resource_id();
1625 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1627 ASSERT_TRUE(EntryExists(src_parent_path));
1628 scoped_ptr<DriveEntryProto> src_parent_proto = GetEntryInfoByPathSync(
1629 src_parent_path);
1630 ASSERT_TRUE(src_parent_proto.get());
1631 ASSERT_TRUE(src_parent_proto->file_info().is_directory());
1632 EXPECT_FALSE(src_parent_proto->content_url().empty());
1634 EXPECT_CALL(*mock_drive_service_,
1635 RenameResource(GURL(src_entry_proto->edit_url()),
1636 FILE_PATH_LITERAL("Test.log"), _));
1637 EXPECT_CALL(*mock_drive_service_,
1638 RemoveResourceFromDirectory(
1639 GURL(src_parent_proto->content_url()),
1640 GURL(src_entry_proto->edit_url()),
1641 src_file_resource_id, _));
1643 FileOperationCallback callback =
1644 base::Bind(&CallbackHelper::FileOperationCallback,
1645 callback_helper_.get());
1647 // Expect notification for both source and destination directories.
1648 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1649 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1650 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1651 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1653 file_system_->Move(src_file_path, dest_file_path, callback);
1654 google_apis::test_util::RunBlockingPoolTask();
1655 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1657 EXPECT_FALSE(EntryExists(src_file_path));
1658 ASSERT_TRUE(EntryExists(dest_file_path));
1659 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1662 TEST_F(DriveFileSystemTest, MoveFileBetweenSubDirectories) {
1663 FilePath src_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1664 FilePath src_file_path(
1665 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1666 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/New Folder 1"));
1667 FilePath dest_file_path(FILE_PATH_LITERAL("drive/New Folder 1/Test.log"));
1668 FilePath interim_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1670 LoadRootFeedDocument("gdata/root_feed.json");
1672 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1673 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1675 AddDirectoryFromFile(dest_parent_path, "gdata/directory_entry_atom.json");
1677 ASSERT_TRUE(EntryExists(src_file_path));
1678 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1679 src_file_path);
1680 ASSERT_TRUE(src_entry_proto.get());
1681 std::string src_file_resource_id =
1682 src_entry_proto->resource_id();
1683 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1685 ASSERT_TRUE(EntryExists(src_parent_path));
1686 scoped_ptr<DriveEntryProto> src_parent_proto = GetEntryInfoByPathSync(
1687 src_parent_path);
1688 ASSERT_TRUE(src_parent_proto.get());
1689 ASSERT_TRUE(src_parent_proto->file_info().is_directory());
1690 EXPECT_FALSE(src_parent_proto->content_url().empty());
1692 ASSERT_TRUE(EntryExists(dest_parent_path));
1693 scoped_ptr<DriveEntryProto> dest_parent_proto = GetEntryInfoByPathSync(
1694 dest_parent_path);
1695 ASSERT_TRUE(dest_parent_proto.get());
1696 ASSERT_TRUE(dest_parent_proto->file_info().is_directory());
1697 EXPECT_FALSE(dest_parent_proto->content_url().empty());
1699 EXPECT_FALSE(EntryExists(interim_file_path));
1701 EXPECT_CALL(*mock_drive_service_,
1702 RenameResource(GURL(src_entry_proto->edit_url()),
1703 FILE_PATH_LITERAL("Test.log"), _));
1704 EXPECT_CALL(*mock_drive_service_,
1705 RemoveResourceFromDirectory(
1706 GURL(src_parent_proto->content_url()),
1707 GURL(src_entry_proto->edit_url()),
1708 src_file_resource_id, _));
1709 EXPECT_CALL(*mock_drive_service_,
1710 AddResourceToDirectory(
1711 GURL(dest_parent_proto->content_url()),
1712 GURL(src_entry_proto->edit_url()),
1713 _));
1715 FileOperationCallback callback =
1716 base::Bind(&CallbackHelper::FileOperationCallback,
1717 callback_helper_.get());
1719 // Expect notification for both source and destination directories plus
1720 // interim file path.
1721 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1722 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1723 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1724 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1725 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1726 Eq(FilePath(FILE_PATH_LITERAL("drive/New Folder 1"))))).Times(1);
1728 file_system_->Move(src_file_path, dest_file_path, callback);
1729 google_apis::test_util::RunBlockingPoolTask();
1730 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1732 EXPECT_FALSE(EntryExists(src_file_path));
1733 EXPECT_FALSE(EntryExists(interim_file_path));
1735 EXPECT_FALSE(EntryExists(src_file_path));
1736 EXPECT_TRUE(EntryExists(dest_file_path));
1737 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1740 TEST_F(DriveFileSystemTest, MoveNotExistingFile) {
1741 FilePath src_file_path(FILE_PATH_LITERAL("drive/Dummy file.txt"));
1742 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1744 LoadRootFeedDocument("gdata/root_feed.json");
1746 EXPECT_FALSE(EntryExists(src_file_path));
1748 FileOperationCallback callback =
1749 base::Bind(&CallbackHelper::FileOperationCallback,
1750 callback_helper_.get());
1752 file_system_->Move(src_file_path, dest_file_path, callback);
1753 google_apis::test_util::RunBlockingPoolTask();
1754 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1756 EXPECT_FALSE(EntryExists(src_file_path));
1757 EXPECT_FALSE(EntryExists(dest_file_path));
1760 TEST_F(DriveFileSystemTest, MoveFileToNonExistingDirectory) {
1761 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1762 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Dummy"));
1763 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Dummy/Test.log"));
1765 LoadRootFeedDocument("gdata/root_feed.json");
1767 ASSERT_TRUE(EntryExists(src_file_path));
1768 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1769 src_file_path);
1770 ASSERT_TRUE(src_entry_proto.get());
1771 std::string src_file_resource_id =
1772 src_entry_proto->resource_id();
1773 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1775 EXPECT_FALSE(EntryExists(dest_parent_path));
1777 FileOperationCallback callback =
1778 base::Bind(&CallbackHelper::FileOperationCallback,
1779 callback_helper_.get());
1781 file_system_->Move(src_file_path, dest_file_path, callback);
1782 google_apis::test_util::RunBlockingPoolTask();
1783 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1786 EXPECT_FALSE(EntryExists(dest_parent_path));
1787 EXPECT_FALSE(EntryExists(dest_file_path));
1790 // Test the case where the parent of |dest_file_path| is a existing file,
1791 // not a directory.
1792 TEST_F(DriveFileSystemTest, MoveFileToInvalidPath) {
1793 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1794 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Duplicate Name.txt"));
1795 FilePath dest_file_path(FILE_PATH_LITERAL(
1796 "drive/Duplicate Name.txt/Test.log"));
1798 LoadRootFeedDocument("gdata/root_feed.json");
1800 ASSERT_TRUE(EntryExists(src_file_path));
1801 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1802 src_file_path);
1803 ASSERT_TRUE(src_entry_proto.get());
1804 std::string src_file_resource_id =
1805 src_entry_proto->resource_id();
1806 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1808 ASSERT_TRUE(EntryExists(dest_parent_path));
1809 scoped_ptr<DriveEntryProto> dest_parent_proto = GetEntryInfoByPathSync(
1810 dest_parent_path);
1811 ASSERT_TRUE(dest_parent_proto.get());
1813 FileOperationCallback callback =
1814 base::Bind(&CallbackHelper::FileOperationCallback,
1815 callback_helper_.get());
1817 file_system_->Move(src_file_path, dest_file_path, callback);
1818 google_apis::test_util::RunBlockingPoolTask();
1819 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_A_DIRECTORY,
1820 callback_helper_->last_error_);
1822 EXPECT_TRUE(EntryExists(src_file_path));
1823 EXPECT_TRUE(EntryExists(dest_parent_path));
1824 EXPECT_FALSE(EntryExists(dest_file_path));
1827 TEST_F(DriveFileSystemTest, RemoveEntries) {
1828 LoadRootFeedDocument("gdata/root_feed.json");
1830 FilePath nonexisting_file(FILE_PATH_LITERAL("drive/Dummy file.txt"));
1831 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
1832 FilePath dir_in_root(FILE_PATH_LITERAL("drive/Directory 1"));
1833 FilePath file_in_subdir(
1834 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1836 ASSERT_TRUE(EntryExists(file_in_root));
1837 scoped_ptr<DriveEntryProto> file_in_root_proto = GetEntryInfoByPathSync(
1838 file_in_root);
1839 ASSERT_TRUE(file_in_root_proto.get());
1841 ASSERT_TRUE(EntryExists(dir_in_root));
1842 scoped_ptr<DriveEntryProto> dir_in_root_proto = GetEntryInfoByPathSync(
1843 dir_in_root);
1844 ASSERT_TRUE(dir_in_root_proto.get());
1845 ASSERT_TRUE(dir_in_root_proto->file_info().is_directory());
1847 ASSERT_TRUE(EntryExists(file_in_subdir));
1848 scoped_ptr<DriveEntryProto> file_in_subdir_proto = GetEntryInfoByPathSync(
1849 file_in_subdir);
1850 ASSERT_TRUE(file_in_subdir_proto.get());
1852 // Once for file in root and once for file...
1853 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1854 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(2);
1856 // Remove first file in root.
1857 EXPECT_TRUE(RemoveEntry(file_in_root));
1858 EXPECT_FALSE(EntryExists(file_in_root));
1859 EXPECT_TRUE(EntryExists(dir_in_root));
1860 EXPECT_TRUE(EntryExists(file_in_subdir));
1862 // Remove directory.
1863 EXPECT_TRUE(RemoveEntry(dir_in_root));
1864 EXPECT_FALSE(EntryExists(file_in_root));
1865 EXPECT_FALSE(EntryExists(dir_in_root));
1866 EXPECT_FALSE(EntryExists(file_in_subdir));
1868 // Try removing file in already removed subdirectory.
1869 EXPECT_FALSE(RemoveEntry(file_in_subdir));
1871 // Try removing non-existing file.
1872 EXPECT_FALSE(RemoveEntry(nonexisting_file));
1874 // Try removing root file element.
1875 EXPECT_FALSE(RemoveEntry(FilePath(FILE_PATH_LITERAL("drive"))));
1877 // Need this to ensure OnDirectoryChanged() is run.
1878 google_apis::test_util::RunBlockingPoolTask();
1881 TEST_F(DriveFileSystemTest, CreateDirectory) {
1882 LoadRootFeedDocument("gdata/root_feed.json");
1884 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1885 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1887 // Create directory in root.
1888 FilePath dir_path(FILE_PATH_LITERAL("drive/New Folder 1"));
1889 EXPECT_FALSE(EntryExists(dir_path));
1890 AddDirectoryFromFile(dir_path, "gdata/directory_entry_atom.json");
1891 EXPECT_TRUE(EntryExists(dir_path));
1893 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1894 Eq(FilePath(FILE_PATH_LITERAL("drive/New Folder 1"))))).Times(1);
1896 // Create directory in a sub directory.
1897 FilePath subdir_path(FILE_PATH_LITERAL("drive/New Folder 1/New Folder 2"));
1898 EXPECT_FALSE(EntryExists(subdir_path));
1899 AddDirectoryFromFile(subdir_path, "gdata/directory_entry_atom2.json");
1900 EXPECT_TRUE(EntryExists(subdir_path));
1903 TEST_F(DriveFileSystemTest, FindFirstMissingParentDirectory) {
1904 LoadRootFeedDocument("gdata/root_feed.json");
1906 DriveFileSystem::FindFirstMissingParentDirectoryResult result;
1908 // Create directory in root.
1909 FilePath dir_path(FILE_PATH_LITERAL("drive/New Folder 1"));
1910 file_system_->FindFirstMissingParentDirectory(
1911 dir_path,
1912 base::Bind(&CopyResultFromFindFirstMissingParentDirectory,
1913 &result));
1914 google_apis::test_util::RunBlockingPoolTask();
1915 EXPECT_EQ(DriveFileSystem::FIND_FIRST_FOUND_MISSING, result.error);
1916 EXPECT_EQ(FilePath(FILE_PATH_LITERAL("drive/New Folder 1")),
1917 result.first_missing_parent_path);
1918 EXPECT_TRUE(result.last_dir_content_url.is_empty()); // root directory.
1920 // Missing folders in subdir of an existing folder.
1921 FilePath dir_path2(FILE_PATH_LITERAL("drive/Directory 1/New Folder 2"));
1922 file_system_->FindFirstMissingParentDirectory(
1923 dir_path2,
1924 base::Bind(&CopyResultFromFindFirstMissingParentDirectory,
1925 &result));
1926 google_apis::test_util::RunBlockingPoolTask();
1927 EXPECT_EQ(DriveFileSystem::FIND_FIRST_FOUND_MISSING, result.error);
1928 EXPECT_EQ(FilePath(FILE_PATH_LITERAL("drive/Directory 1/New Folder 2")),
1929 result.first_missing_parent_path);
1930 EXPECT_FALSE(result.last_dir_content_url.is_empty()); // non-root dir.
1932 // Missing two folders on the path.
1933 FilePath dir_path3 = dir_path2.Append(FILE_PATH_LITERAL("Another Folder"));
1934 file_system_->FindFirstMissingParentDirectory(
1935 dir_path3,
1936 base::Bind(&CopyResultFromFindFirstMissingParentDirectory,
1937 &result));
1938 google_apis::test_util::RunBlockingPoolTask();
1939 EXPECT_EQ(DriveFileSystem::FIND_FIRST_FOUND_MISSING, result.error);
1940 EXPECT_EQ(FilePath(FILE_PATH_LITERAL("drive/Directory 1/New Folder 2")),
1941 result.first_missing_parent_path);
1942 EXPECT_FALSE(result.last_dir_content_url.is_empty()); // non-root dir.
1944 // Folders on top of an existing file.
1945 file_system_->FindFirstMissingParentDirectory(
1946 FilePath(FILE_PATH_LITERAL("drive/File 1.txt/BadDir")),
1947 base::Bind(&CopyResultFromFindFirstMissingParentDirectory,
1948 &result));
1949 google_apis::test_util::RunBlockingPoolTask();
1950 EXPECT_EQ(DriveFileSystem::FIND_FIRST_FOUND_INVALID, result.error);
1952 // Existing folder.
1953 file_system_->FindFirstMissingParentDirectory(
1954 FilePath(FILE_PATH_LITERAL("drive/Directory 1")),
1955 base::Bind(&CopyResultFromFindFirstMissingParentDirectory,
1956 &result));
1957 google_apis::test_util::RunBlockingPoolTask();
1958 EXPECT_EQ(DriveFileSystem::FIND_FIRST_DIRECTORY_ALREADY_PRESENT,
1959 result.error);
1962 // Create a directory through the document service
1963 TEST_F(DriveFileSystemTest, CreateDirectoryWithService) {
1964 LoadRootFeedDocument("gdata/root_feed.json");
1965 EXPECT_CALL(*mock_drive_service_,
1966 CreateDirectory(_, "Sample Directory Title", _)).Times(1);
1967 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1968 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1970 // Set last error so it's not a valid error code.
1971 callback_helper_->last_error_ = static_cast<DriveFileError>(1);
1972 file_system_->CreateDirectory(
1973 FilePath(FILE_PATH_LITERAL("drive/Sample Directory Title")),
1974 false, // is_exclusive
1975 true, // is_recursive
1976 base::Bind(&CallbackHelper::FileOperationCallback,
1977 callback_helper_.get()));
1978 google_apis::test_util::RunBlockingPoolTask();
1979 // TODO(gspencer): Uncomment this when we get a blob that
1980 // works that can be returned from the mock.
1981 // EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1984 TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_EnoughSpace) {
1985 LoadRootFeedDocument("gdata/root_feed.json");
1987 GetFileCallback callback =
1988 base::Bind(&CallbackHelper::GetFileCallback,
1989 callback_helper_.get());
1991 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
1992 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
1993 FilePath downloaded_file = GetCachePathForFile(
1994 entry_proto->resource_id(),
1995 entry_proto->file_specific_info().file_md5());
1996 const int64 file_size = entry_proto->file_info().size();
1998 // Pretend we have enough space.
1999 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2000 .Times(2).WillRepeatedly(Return(file_size + kMinFreeSpace));
2002 // Before Download starts metadata from server will be fetched.
2003 // We will read content url from the result.
2004 scoped_ptr<base::Value> document =
2005 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
2006 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2008 // The file is obtained with the mock DriveService.
2009 EXPECT_CALL(*mock_drive_service_,
2010 DownloadFile(file_in_root,
2011 downloaded_file,
2012 GURL("https://file_content_url_changed/"),
2013 _, _))
2014 .Times(1);
2016 file_system_->GetFileByPath(file_in_root, callback,
2017 google_apis::GetContentCallback());
2018 google_apis::test_util::RunBlockingPoolTask();
2020 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2021 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2022 EXPECT_EQ(downloaded_file.value(),
2023 callback_helper_->download_path_.value());
2026 TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_NoSpaceAtAll) {
2027 LoadRootFeedDocument("gdata/root_feed.json");
2029 GetFileCallback callback =
2030 base::Bind(&CallbackHelper::GetFileCallback,
2031 callback_helper_.get());
2033 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2034 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2035 FilePath downloaded_file = GetCachePathForFile(
2036 entry_proto->resource_id(),
2037 entry_proto->file_specific_info().file_md5());
2039 // Pretend we have no space at all.
2040 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2041 .Times(2).WillRepeatedly(Return(0));
2043 // Before Download starts metadata from server will be fetched.
2044 // We will read content url from the result.
2045 scoped_ptr<base::Value> document =
2046 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
2047 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2049 // The file is not obtained with the mock DriveService, because of no space.
2050 EXPECT_CALL(*mock_drive_service_,
2051 DownloadFile(file_in_root,
2052 downloaded_file,
2053 GURL("https://file_content_url_changed/"),
2054 _, _))
2055 .Times(0);
2057 file_system_->GetFileByPath(file_in_root, callback,
2058 google_apis::GetContentCallback());
2059 google_apis::test_util::RunBlockingPoolTask();
2061 EXPECT_EQ(DRIVE_FILE_ERROR_NO_SPACE,
2062 callback_helper_->last_error_);
2065 TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_NoEnoughSpaceButCanFreeUp) {
2066 LoadRootFeedDocument("gdata/root_feed.json");
2068 GetFileCallback callback =
2069 base::Bind(&CallbackHelper::GetFileCallback,
2070 callback_helper_.get());
2072 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2073 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2074 FilePath downloaded_file = GetCachePathForFile(
2075 entry_proto->resource_id(),
2076 entry_proto->file_specific_info().file_md5());
2077 const int64 file_size = entry_proto->file_info().size();
2079 // Pretend we have no space first (checked before downloading a file),
2080 // but then start reporting we have space. This is to emulate that
2081 // the disk space was freed up by removing temporary files.
2082 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2083 .WillOnce(Return(file_size + kMinFreeSpace))
2084 .WillOnce(Return(0))
2085 .WillOnce(Return(file_size + kMinFreeSpace))
2086 .WillOnce(Return(file_size + kMinFreeSpace));
2088 // Store something in the temporary cache directory.
2089 TestStoreToCache("<resource_id>",
2090 "<md5>",
2091 google_apis::test_util::GetTestFilePath(
2092 "gdata/root_feed.json"),
2093 DRIVE_FILE_OK,
2094 test_util::TEST_CACHE_STATE_PRESENT,
2095 DriveCache::CACHE_TYPE_TMP);
2096 ASSERT_TRUE(CacheEntryExists("<resource_id>", "<md5>"));
2097 ASSERT_TRUE(CacheFileExists("<resource_id>", "<md5>"));
2099 // Before Download starts metadata from server will be fetched.
2100 // We will read content url from the result.
2101 scoped_ptr<base::Value> document =
2102 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
2103 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2105 // The file is obtained with the mock DriveService, because of we freed up the
2106 // space.
2107 EXPECT_CALL(*mock_drive_service_,
2108 DownloadFile(file_in_root,
2109 downloaded_file,
2110 GURL("https://file_content_url_changed/"),
2111 _, _))
2112 .Times(1);
2114 file_system_->GetFileByPath(file_in_root, callback,
2115 google_apis::GetContentCallback());
2116 google_apis::test_util::RunBlockingPoolTask();
2118 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2119 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2120 EXPECT_EQ(downloaded_file.value(),
2121 callback_helper_->download_path_.value());
2123 // The file should be removed in order to free up space, and the cache
2124 // entry should also be removed.
2125 ASSERT_FALSE(CacheEntryExists("<resource_id>", "<md5>"));
2126 ASSERT_FALSE(CacheFileExists("<resource_id>", "<md5>"));
2129 TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_EnoughSpaceButBecomeFull) {
2130 LoadRootFeedDocument("gdata/root_feed.json");
2132 GetFileCallback callback =
2133 base::Bind(&CallbackHelper::GetFileCallback,
2134 callback_helper_.get());
2136 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2137 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2138 FilePath downloaded_file = GetCachePathForFile(
2139 entry_proto->resource_id(),
2140 entry_proto->file_specific_info().file_md5());
2141 const int64 file_size = entry_proto->file_info().size();
2143 // Pretend we have enough space first (checked before downloading a file),
2144 // but then start reporting we have not enough space. This is to emulate that
2145 // the disk space becomes full after the file is downloaded for some reason
2146 // (ex. the actual file was larger than the expected size).
2147 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2148 .WillOnce(Return(file_size + kMinFreeSpace))
2149 .WillOnce(Return(kMinFreeSpace - 1))
2150 .WillOnce(Return(kMinFreeSpace - 1));
2152 // Before Download starts metadata from server will be fetched.
2153 // We will read content url from the result.
2154 scoped_ptr<base::Value> document =
2155 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
2156 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2158 // The file is obtained with the mock DriveService.
2159 EXPECT_CALL(*mock_drive_service_,
2160 DownloadFile(file_in_root,
2161 downloaded_file,
2162 GURL("https://file_content_url_changed/"),
2163 _, _))
2164 .Times(1);
2166 file_system_->GetFileByPath(file_in_root, callback,
2167 google_apis::GetContentCallback());
2168 google_apis::test_util::RunBlockingPoolTask();
2170 EXPECT_EQ(DRIVE_FILE_ERROR_NO_SPACE,
2171 callback_helper_->last_error_);
2174 TEST_F(DriveFileSystemTest, GetFileByPath_FromCache) {
2175 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2176 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2178 LoadRootFeedDocument("gdata/root_feed.json");
2180 GetFileCallback callback =
2181 base::Bind(&CallbackHelper::GetFileCallback,
2182 callback_helper_.get());
2184 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2185 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2186 FilePath downloaded_file = GetCachePathForFile(
2187 entry_proto->resource_id(),
2188 entry_proto->file_specific_info().file_md5());
2190 // Store something as cached version of this file.
2191 TestStoreToCache(entry_proto->resource_id(),
2192 entry_proto->file_specific_info().file_md5(),
2193 google_apis::test_util::GetTestFilePath(
2194 "gdata/root_feed.json"),
2195 DRIVE_FILE_OK,
2196 test_util::TEST_CACHE_STATE_PRESENT,
2197 DriveCache::CACHE_TYPE_TMP);
2199 // Make sure we don't fetch metadata for downloading file.
2200 EXPECT_CALL(*mock_drive_service_, GetDocumentEntry(_, _)).Times(0);
2202 // Make sure we don't call downloads at all.
2203 EXPECT_CALL(*mock_drive_service_,
2204 DownloadFile(file_in_root,
2205 downloaded_file,
2206 GURL("https://file_content_url_changed/"),
2207 _, _))
2208 .Times(0);
2210 file_system_->GetFileByPath(file_in_root, callback,
2211 google_apis::GetContentCallback());
2212 google_apis::test_util::RunBlockingPoolTask();
2214 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2215 EXPECT_EQ(downloaded_file.value(),
2216 callback_helper_->download_path_.value());
2219 TEST_F(DriveFileSystemTest, GetFileByPath_HostedDocument) {
2220 LoadRootFeedDocument("gdata/root_feed.json");
2222 GetFileCallback callback =
2223 base::Bind(&CallbackHelper::GetFileCallback,
2224 callback_helper_.get());
2226 FilePath file_in_root(FILE_PATH_LITERAL("drive/Document 1.gdoc"));
2227 scoped_ptr<DriveEntryProto> src_entry_proto =
2228 GetEntryInfoByPathSync(file_in_root);
2229 ASSERT_TRUE(src_entry_proto.get());
2231 file_system_->GetFileByPath(file_in_root, callback,
2232 google_apis::GetContentCallback());
2233 google_apis::test_util::RunBlockingPoolTask();
2235 EXPECT_EQ(HOSTED_DOCUMENT, callback_helper_->file_type_);
2236 EXPECT_FALSE(callback_helper_->download_path_.empty());
2238 ASSERT_TRUE(src_entry_proto.get());
2239 VerifyHostedDocumentJSONFile(*src_entry_proto,
2240 callback_helper_->download_path_);
2243 TEST_F(DriveFileSystemTest, GetFileByResourceId) {
2244 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2245 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2247 LoadRootFeedDocument("gdata/root_feed.json");
2249 GetFileCallback callback =
2250 base::Bind(&CallbackHelper::GetFileCallback,
2251 callback_helper_.get());
2253 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2254 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2255 FilePath downloaded_file = GetCachePathForFile(
2256 entry_proto->resource_id(),
2257 entry_proto->file_specific_info().file_md5());
2259 // Before Download starts metadata from server will be fetched.
2260 // We will read content url from the result.
2261 scoped_ptr<base::Value> document =
2262 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
2263 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2265 // The file is obtained with the mock DriveService, because it's not stored in
2266 // the cache.
2267 EXPECT_CALL(*mock_drive_service_,
2268 DownloadFile(file_in_root,
2269 downloaded_file,
2270 GURL("https://file_content_url_changed/"),
2271 _, _))
2272 .Times(1);
2274 file_system_->GetFileByResourceId(entry_proto->resource_id(),
2275 callback,
2276 google_apis::GetContentCallback());
2277 google_apis::test_util::RunBlockingPoolTask();
2279 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2280 EXPECT_EQ(downloaded_file.value(),
2281 callback_helper_->download_path_.value());
2284 TEST_F(DriveFileSystemTest, GetFileByResourceId_FromCache) {
2285 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2286 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2288 LoadRootFeedDocument("gdata/root_feed.json");
2290 GetFileCallback callback =
2291 base::Bind(&CallbackHelper::GetFileCallback,
2292 callback_helper_.get());
2294 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2295 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2296 FilePath downloaded_file = GetCachePathForFile(
2297 entry_proto->resource_id(),
2298 entry_proto->file_specific_info().file_md5());
2300 // Store something as cached version of this file.
2301 TestStoreToCache(entry_proto->resource_id(),
2302 entry_proto->file_specific_info().file_md5(),
2303 google_apis::test_util::GetTestFilePath(
2304 "gdata/root_feed.json"),
2305 DRIVE_FILE_OK,
2306 test_util::TEST_CACHE_STATE_PRESENT,
2307 DriveCache::CACHE_TYPE_TMP);
2309 // The file is obtained from the cache.
2310 // Make sure we don't call downloads at all.
2311 EXPECT_CALL(*mock_drive_service_, DownloadFile(_, _, _, _, _))
2312 .Times(0);
2314 file_system_->GetFileByResourceId(entry_proto->resource_id(),
2315 callback,
2316 google_apis::GetContentCallback());
2317 google_apis::test_util::RunBlockingPoolTask();
2319 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2320 EXPECT_EQ(downloaded_file.value(),
2321 callback_helper_->download_path_.value());
2324 TEST_F(DriveFileSystemTest, UpdateFileByResourceId_PersistentFile) {
2325 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2326 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2328 LoadRootFeedDocument("gdata/root_feed.json");
2330 // This is a file defined in root_feed.json.
2331 const FilePath kFilePath(FILE_PATH_LITERAL("drive/File 1.txt"));
2332 const std::string kResourceId("file:2_file_resource_id");
2333 const std::string kMd5("3b4382ebefec6e743578c76bbd0575ce");
2335 // Pin the file so it'll be store in "persistent" directory.
2336 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(kResourceId, kMd5)).Times(1);
2337 TestPin(kResourceId,
2338 kMd5,
2339 DRIVE_FILE_OK,
2340 test_util::TEST_CACHE_STATE_PINNED,
2341 DriveCache::CACHE_TYPE_TMP);
2343 // First store a file to cache. A cache file will be created at:
2344 // GCache/v1/persistent/<kResourceId>.<kMd5>
2345 const FilePath original_cache_file_path =
2346 DriveCache::GetCacheRootPath(profile_.get())
2347 .AppendASCII("persistent")
2348 .AppendASCII(kResourceId + "." + kMd5);
2349 TestStoreToCache(kResourceId,
2350 kMd5,
2351 // Anything works.
2352 google_apis::test_util::GetTestFilePath(
2353 "gdata/root_feed.json"),
2354 DRIVE_FILE_OK,
2355 test_util::TEST_CACHE_STATE_PRESENT |
2356 test_util::TEST_CACHE_STATE_PINNED |
2357 test_util::TEST_CACHE_STATE_PERSISTENT,
2358 DriveCache::CACHE_TYPE_PERSISTENT);
2359 ASSERT_TRUE(file_util::PathExists(original_cache_file_path));
2361 // Add the dirty bit. The cache file will be renamed to
2362 // GCache/v1/persistent/<kResourceId>.local
2363 TestMarkDirty(kResourceId,
2364 kMd5,
2365 DRIVE_FILE_OK,
2366 test_util::TEST_CACHE_STATE_PRESENT |
2367 test_util::TEST_CACHE_STATE_PINNED |
2368 test_util::TEST_CACHE_STATE_DIRTY |
2369 test_util::TEST_CACHE_STATE_PERSISTENT,
2370 DriveCache::CACHE_TYPE_PERSISTENT);
2371 const FilePath dirty_cache_file_path =
2372 DriveCache::GetCacheRootPath(profile_.get())
2373 .AppendASCII("persistent")
2374 .AppendASCII(kResourceId + ".local");
2375 ASSERT_FALSE(file_util::PathExists(original_cache_file_path));
2376 ASSERT_TRUE(file_util::PathExists(dirty_cache_file_path));
2378 // Modify the cached file.
2379 const std::string kDummyCacheContent("modification to the cache");
2380 ASSERT_TRUE(file_util::WriteFile(dirty_cache_file_path,
2381 kDummyCacheContent.c_str(),
2382 kDummyCacheContent.size()));
2384 // Commit the dirty bit. The cache file name remains the same
2385 // but a symlink will be created at:
2386 // GCache/v1/outgoing/<kResourceId>
2387 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(kResourceId)).Times(1);
2388 TestCommitDirty(kResourceId,
2389 kMd5,
2390 DRIVE_FILE_OK,
2391 test_util::TEST_CACHE_STATE_PRESENT |
2392 test_util::TEST_CACHE_STATE_PINNED |
2393 test_util::TEST_CACHE_STATE_DIRTY |
2394 test_util::TEST_CACHE_STATE_PERSISTENT,
2395 DriveCache::CACHE_TYPE_PERSISTENT);
2396 const FilePath outgoing_symlink_path =
2397 DriveCache::GetCacheRootPath(profile_.get())
2398 .AppendASCII("outgoing")
2399 .AppendASCII(kResourceId);
2400 ASSERT_TRUE(file_util::PathExists(dirty_cache_file_path));
2401 ASSERT_TRUE(file_util::PathExists(outgoing_symlink_path));
2403 // Create a google_apis::DocumentEntry, which is needed to mock
2404 // DriveUploaderInterface::UploadExistingFile().
2405 // TODO(satorux): This should be cleaned up. crbug.com/134240.
2406 google_apis::DocumentEntry* document_entry = NULL;
2407 scoped_ptr<base::Value> value =
2408 google_apis::test_util::LoadJSONFile("gdata/root_feed.json");
2409 ASSERT_TRUE(value.get());
2410 base::DictionaryValue* as_dict = NULL;
2411 base::ListValue* entry_list = NULL;
2412 if (value->GetAsDictionary(&as_dict) &&
2413 as_dict->GetList("feed.entry", &entry_list)) {
2414 for (size_t i = 0; i < entry_list->GetSize(); ++i) {
2415 base::DictionaryValue* entry = NULL;
2416 std::string resource_id;
2417 if (entry_list->GetDictionary(i, &entry) &&
2418 entry->GetString("gd$resourceId.$t", &resource_id) &&
2419 resource_id == kResourceId) {
2420 // This will be deleted by UploadExistingFile().
2421 document_entry = google_apis::DocumentEntry::CreateFrom(*entry);
2425 ASSERT_TRUE(document_entry);
2427 // The mock uploader will be used to simulate a file upload.
2428 EXPECT_CALL(*mock_uploader_, UploadExistingFile(
2429 GURL("https://file_link_resumable_edit_media/"),
2430 kFilePath,
2431 dirty_cache_file_path,
2432 "audio/mpeg",
2433 kDummyCacheContent.size(), // The size after modification must be used.
2434 _, // Completion callback.
2435 _)) // Ready callback.
2436 .WillOnce(MockUploadExistingFile(
2437 google_apis::DRIVE_UPLOAD_OK,
2438 FilePath::FromUTF8Unsafe("drive/File1"),
2439 dirty_cache_file_path,
2440 document_entry));
2442 // We'll notify the directory change to the observer upon completion.
2443 EXPECT_CALL(*mock_directory_observer_,
2444 OnDirectoryChanged(Eq(FilePath(kDriveRootDirectory)))).Times(1);
2446 // The callback will be called upon completion of
2447 // UpdateFileByResourceId().
2448 FileOperationCallback callback =
2449 base::Bind(&CallbackHelper::FileOperationCallback,
2450 callback_helper_.get());
2452 // Check the number of files in the root directory. We'll compare the
2453 // number after updating a file.
2454 scoped_ptr<DriveEntryProtoVector> root_directory_entries(
2455 ReadDirectoryByPathSync(FilePath::FromUTF8Unsafe("drive")));
2456 ASSERT_TRUE(root_directory_entries.get());
2457 const int num_files_in_root = CountFiles(*root_directory_entries);
2459 file_system_->UpdateFileByResourceId(kResourceId, callback);
2460 google_apis::test_util::RunBlockingPoolTask();
2462 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2463 // Make sure that the number of files did not change (i.e. we updated an
2464 // existing file, rather than adding a new file. The number of files
2465 // increases if we don't handle the file update right).
2466 EXPECT_EQ(num_files_in_root, CountFiles(*root_directory_entries));
2467 // After the file is updated, the dirty bit is cleared, hence the symlink
2468 // should be gone.
2469 ASSERT_FALSE(file_util::PathExists(outgoing_symlink_path));
2472 TEST_F(DriveFileSystemTest, UpdateFileByResourceId_NonexistentFile) {
2473 LoadRootFeedDocument("gdata/root_feed.json");
2475 // This is nonexistent in root_feed.json.
2476 const FilePath kFilePath(FILE_PATH_LITERAL("drive/Nonexistent.txt"));
2477 const std::string kResourceId("file:nonexistent_resource_id");
2478 const std::string kMd5("nonexistent_md5");
2480 // The callback will be called upon completion of
2481 // UpdateFileByResourceId().
2482 FileOperationCallback callback =
2483 base::Bind(&CallbackHelper::FileOperationCallback,
2484 callback_helper_.get());
2486 file_system_->UpdateFileByResourceId(kResourceId, callback);
2487 google_apis::test_util::RunBlockingPoolTask();
2488 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
2491 TEST_F(DriveFileSystemTest, ContentSearch) {
2492 LoadRootFeedDocument("gdata/root_feed.json");
2494 mock_drive_service_->set_search_result("gdata/search_result_feed.json");
2496 // There should be only one GetDocuments request, even though search result
2497 // feed has next feed url.
2498 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "foo", _, _))
2499 .Times(1);
2501 const SearchResultPair kExpectedResults[] = {
2502 { "drive/Directory 1/SubDirectory File 1.txt", false },
2503 { "drive/Directory 1", true }
2506 SearchCallback callback = base::Bind(&DriveSearchCallback,
2507 &message_loop_,
2508 kExpectedResults, ARRAYSIZE_UNSAFE(kExpectedResults),
2509 GURL("https://next_feed"));
2511 file_system_->Search("foo", GURL(), callback);
2512 message_loop_.Run(); // Wait to get our result.
2515 TEST_F(DriveFileSystemTest, ContentSearchWithNewEntry) {
2516 LoadRootFeedDocument("gdata/root_feed.json");
2518 // Search result returning two entries "Directory 1/" and
2519 // "Directory 1/SubDirectory Newly Added File.txt". The latter is not
2520 // contained in the root feed.
2521 mock_drive_service_->set_search_result(
2522 "gdata/search_result_with_new_entry_feed.json");
2524 // There should be only one GetDocuments request, even though search result
2525 // feed has next feed url.
2526 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "foo", _, _))
2527 .Times(1);
2529 // As the result of the first Search(), only entries in the current file
2530 // system snapshot are expected to be returned.
2531 const SearchResultPair kExpectedResults[] = {
2532 { "drive/Directory 1", true }
2535 // At the same time, unknown entry should trigger delta feed request.
2536 // This will cause notification to observers (e.g., File Browser) so that
2537 // they can request search again.
2538 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
2539 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "", _, _))
2540 .Times(1);
2541 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
2543 SearchCallback callback = base::Bind(&DriveSearchCallback,
2544 &message_loop_,
2545 kExpectedResults, ARRAYSIZE_UNSAFE(kExpectedResults),
2546 GURL("https://next_feed"));
2548 file_system_->Search("foo", GURL(), callback);
2549 message_loop_.Run(); // Wait to get our result.
2552 TEST_F(DriveFileSystemTest, ContentSearchEmptyResult) {
2553 LoadRootFeedDocument("gdata/root_feed.json");
2555 mock_drive_service_->set_search_result("gdata/empty_feed.json");
2557 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "foo", _, _))
2558 .Times(1);
2560 const SearchResultPair* expected_results = NULL;
2562 SearchCallback callback = base::Bind(&DriveSearchCallback,
2563 &message_loop_, expected_results, 0u, GURL());
2565 file_system_->Search("foo", GURL(), callback);
2566 message_loop_.Run(); // Wait to get our result.
2569 TEST_F(DriveFileSystemTest, GetAvailableSpace) {
2570 GetAvailableSpaceCallback callback =
2571 base::Bind(&CallbackHelper::GetAvailableSpaceCallback,
2572 callback_helper_.get());
2574 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_));
2576 file_system_->GetAvailableSpace(callback);
2577 google_apis::test_util::RunBlockingPoolTask();
2578 EXPECT_EQ(GG_LONGLONG(6789012345), callback_helper_->quota_bytes_used_);
2579 EXPECT_EQ(GG_LONGLONG(9876543210), callback_helper_->quota_bytes_total_);
2582 TEST_F(DriveFileSystemTest, RequestDirectoryRefresh) {
2583 LoadRootFeedDocument("gdata/root_feed.json");
2585 // We'll fetch documents in the root directory with its resource ID.
2586 // kWAPIRootDirectoryResourceId instead of kTestRootDirectoryResourceId
2587 // is used here as the root ID is set in DriveFeedLoader::UpdateFromFeed().
2588 EXPECT_CALL(*mock_drive_service_,
2589 GetDocuments(Eq(GURL()), _, _, kWAPIRootDirectoryResourceId, _))
2590 .Times(1);
2591 // We'll notify the directory change to the observer.
2592 EXPECT_CALL(*mock_directory_observer_,
2593 OnDirectoryChanged(Eq(FilePath(kDriveRootDirectory)))).Times(1);
2595 file_system_->RequestDirectoryRefresh(FilePath(kDriveRootDirectory));
2596 google_apis::test_util::RunBlockingPoolTask();
2599 TEST_F(DriveFileSystemTest, OpenAndCloseFile) {
2600 LoadRootFeedDocument("gdata/root_feed.json");
2602 OpenFileCallback callback =
2603 base::Bind(&CallbackHelper::OpenFileCallback,
2604 callback_helper_.get());
2605 FileOperationCallback close_file_callback =
2606 base::Bind(&CallbackHelper::CloseFileCallback,
2607 callback_helper_.get());
2609 const FilePath kFileInRoot(FILE_PATH_LITERAL("drive/File 1.txt"));
2610 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(kFileInRoot));
2611 FilePath downloaded_file = GetCachePathForFile(
2612 entry_proto->resource_id(),
2613 entry_proto->file_specific_info().file_md5());
2614 const int64 file_size = entry_proto->file_info().size();
2615 const std::string& file_resource_id =
2616 entry_proto->resource_id();
2617 const std::string& file_md5 = entry_proto->file_specific_info().file_md5();
2619 // A dirty file is created on close.
2620 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(file_resource_id))
2621 .Times(1);
2623 // Pretend we have enough space.
2624 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2625 .Times(2).WillRepeatedly(Return(file_size + kMinFreeSpace));
2627 const std::string kExpectedFileData = "test file data";
2628 mock_drive_service_->set_file_data(new std::string(kExpectedFileData));
2630 // Before Download starts metadata from server will be fetched.
2631 // We will read content url from the result.
2632 scoped_ptr<base::Value> document =
2633 google_apis::test_util::LoadJSONFile("gdata/document_to_download.json");
2634 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2636 // The file is obtained with the mock DriveService.
2637 EXPECT_CALL(*mock_drive_service_,
2638 DownloadFile(kFileInRoot,
2639 downloaded_file,
2640 GURL("https://file_content_url_changed/"),
2641 _, _))
2642 .Times(1);
2644 // Open kFileInRoot ("drive/File 1.txt").
2645 file_system_->OpenFile(kFileInRoot, callback);
2646 message_loop_.Run();
2647 const FilePath opened_file_path = callback_helper_->opened_file_path_;
2649 // Verify that the file was properly opened.
2650 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2652 // Try to open the already opened file.
2653 file_system_->OpenFile(kFileInRoot, callback);
2654 message_loop_.Run();
2656 // It must fail.
2657 EXPECT_EQ(DRIVE_FILE_ERROR_IN_USE, callback_helper_->last_error_);
2659 // Verify that the file contents match the expected contents.
2660 std::string cache_file_data;
2661 EXPECT_TRUE(file_util::ReadFileToString(opened_file_path, &cache_file_data));
2662 EXPECT_EQ(kExpectedFileData, cache_file_data);
2664 // Verify that the cache state was changed as expected.
2665 VerifyCacheStateAfterOpenFile(DRIVE_FILE_OK,
2666 file_resource_id,
2667 file_md5,
2668 opened_file_path);
2670 // Close kFileInRoot ("drive/File 1.txt").
2671 file_system_->CloseFile(kFileInRoot, close_file_callback);
2672 message_loop_.Run();
2674 // Verify that the file was properly closed.
2675 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2677 // Verify that the cache state was changed as expected.
2678 VerifyCacheStateAfterCloseFile(DRIVE_FILE_OK,
2679 file_resource_id,
2680 file_md5);
2682 // Try to close the same file twice.
2683 file_system_->CloseFile(kFileInRoot, close_file_callback);
2684 message_loop_.Run();
2686 // It must fail.
2687 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
2690 } // namespace drive