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"
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
;
44 using ::testing::NotNull
;
45 using ::testing::Return
;
46 using ::testing::StrictMock
;
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
{
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
,
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
),
81 EXPECT_EQ(expected_results
[i
].is_directory
,
82 results
->at(i
).is_directory
);
85 EXPECT_EQ(expected_next_feed
, next_feed
);
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
,
107 base::Passed(&scoped_document_entry
)));
109 const int kUploadId
= 123;
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
,
123 google_apis::DRIVE_UPLOAD_OK
,
126 base::Passed(&document_entry
)));
128 const int kUploadId
= 123;
132 // Action used to set mock expectations for
133 // DriveFileSystem::CopyDocument().
134 ACTION_P2(MockCopyDocument
, status
, value
) {
135 base::MessageLoopProxy::current()->PostTask(
137 base::Bind(arg2
, status
, base::Passed(value
)));
140 ACTION(MockFailingGetDocuments
) {
141 base::MessageLoopProxy::current()->PostTask(
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
) {
150 for (size_t i
= 0; i
< entries
.size(); ++i
) {
151 if (!entries
[i
].file_info().is_directory())
159 class DriveFileSystemTest
: public testing::Test
{
161 DriveFileSystemTest()
162 : ui_thread_(content::BrowserThread::UI
, &message_loop_
),
163 io_thread_(content::BrowserThread::IO
),
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(),
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);
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
,
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
,
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(
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
,
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(
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(
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();
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
) {
349 blocking_task_runner_
->PostTask(
351 base::Bind(&DriveFileSystemTest::GetCacheEntryFromOriginThreadInternal
,
352 base::Unretained(this),
357 google_apis::test_util::RunBlockingPoolTask();
361 // Used to implement GetCacheEntry.
362 void GetCacheEntryFromOriginThreadInternal(
363 const std::string
& resource_id
,
364 const std::string
& md5
,
365 DriveCacheEntry
* cache_entry
,
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(
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();
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(
420 base::Bind(&DriveFileSystemTest::VerifyCacheFileState
,
421 base::Unretained(this)));
423 google_apis::test_util::RunBlockingPoolTask();
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(
440 base::Bind(&DriveFileSystemTest::VerifyMarkDirty
,
441 base::Unretained(this),
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
+
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(
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
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
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
);
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_
),
533 EXPECT_EQ(expected_sub_dir_type_
,
534 DriveCache::GetSubDirectoryType(cache_entry
));
536 EXPECT_FALSE(cache_entry_found
);
539 // Verify actual cache file.
540 FilePath dest_path
= cache_
->GetCacheFilePath(
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())
554 EXPECT_FALSE(exists
);
556 // Verify symlink in pinned dir.
557 FilePath symlink_path
= cache_
->GetCacheFilePath(
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()) {
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
);
571 EXPECT_EQ(kSymLinkToDevNull
, target_path
.value());
573 EXPECT_FALSE(exists
);
576 // Verify symlink in outgoing dir.
577 symlink_path
= cache_
->GetCacheFilePath(
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()) {
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
);
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
{
616 USE_SERVER_TIMESTAMP
,
619 // Creates a proto file representing a filesystem with directories:
620 // drive, drive/Dir1, drive/Dir1/SubDir2
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);
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);
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);
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
) {
704 JSONFileValueSerializer
serializer(file_path
);
705 scoped_ptr
<Value
> value(serializer
.Deserialize(NULL
, &error
));
706 ASSERT_TRUE(value
.get()) << "Parse error " << file_path
.value()
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(),
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
724 : public base::RefCountedThreadSafe
<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
) {
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
));
748 virtual void GetAvailableSpaceCallback(DriveFileError error
,
752 quota_bytes_total_
= bytes_total
;
753 quota_bytes_used_
= bytes_used
;
756 virtual void OpenFileCallback(DriveFileError error
,
757 const FilePath
& file_path
) {
759 opened_file_path_
= file_path
;
760 MessageLoop::current()->Quit();
763 virtual void CloseFileCallback(DriveFileError error
) {
765 MessageLoop::current()->Quit();
768 virtual void GetEntryInfoCallback(
769 DriveFileError error
,
770 scoped_ptr
<DriveEntryProto
> entry_proto
) {
772 entry_proto_
= entry_proto
.Pass();
775 virtual void ReadDirectoryCallback(
776 DriveFileError error
,
777 bool /* hide_hosted_documents */,
778 scoped_ptr
<DriveEntryProtoVector
> entries
) {
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_
;
794 virtual ~CallbackHelper() {}
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
) {
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_
;
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(
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());
848 if (*counter
>= expected_counter
)
849 message_loop
->Quit();
852 TEST_F(DriveFileSystemTest
, DuplicatedAsyncInitialization
) {
854 GetEntryInfoCallback callback
= base::Bind(
855 &AsyncInitializationCallback
,
858 FilePath(FILE_PATH_LITERAL("drive")),
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(
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
);
1025 EntryExists(FilePath(FILE_PATH_LITERAL("drive/Added file.gdoc"))));
1027 LoadChangeFeed("gdata/delta_file_deleted_in_root.json", ++latest_changelog
);
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")))))
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
,
1394 GURL("https://file_content_url_changed/"),
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(
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,
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(
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(
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(
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(
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(
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(
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(
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(
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(
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(
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()),
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(
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,
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(
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(
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(
1839 ASSERT_TRUE(file_in_root_proto
.get());
1841 ASSERT_TRUE(EntryExists(dir_in_root
));
1842 scoped_ptr
<DriveEntryProto
> dir_in_root_proto
= GetEntryInfoByPathSync(
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(
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(
1912 base::Bind(&CopyResultFromFindFirstMissingParentDirectory
,
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(
1924 base::Bind(&CopyResultFromFindFirstMissingParentDirectory
,
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(
1936 base::Bind(&CopyResultFromFindFirstMissingParentDirectory
,
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
,
1949 google_apis::test_util::RunBlockingPoolTask();
1950 EXPECT_EQ(DriveFileSystem::FIND_FIRST_FOUND_INVALID
, result
.error
);
1953 file_system_
->FindFirstMissingParentDirectory(
1954 FilePath(FILE_PATH_LITERAL("drive/Directory 1")),
1955 base::Bind(&CopyResultFromFindFirstMissingParentDirectory
,
1957 google_apis::test_util::RunBlockingPoolTask();
1958 EXPECT_EQ(DriveFileSystem::FIND_FIRST_DIRECTORY_ALREADY_PRESENT
,
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
,
2012 GURL("https://file_content_url_changed/"),
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
,
2053 GURL("https://file_content_url_changed/"),
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>",
2091 google_apis::test_util::GetTestFilePath(
2092 "gdata/root_feed.json"),
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
2107 EXPECT_CALL(*mock_drive_service_
,
2108 DownloadFile(file_in_root
,
2110 GURL("https://file_content_url_changed/"),
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
,
2162 GURL("https://file_content_url_changed/"),
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"),
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
,
2206 GURL("https://file_content_url_changed/"),
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
2267 EXPECT_CALL(*mock_drive_service_
,
2268 DownloadFile(file_in_root
,
2270 GURL("https://file_content_url_changed/"),
2274 file_system_
->GetFileByResourceId(entry_proto
->resource_id(),
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"),
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(_
, _
, _
, _
, _
))
2314 file_system_
->GetFileByResourceId(entry_proto
->resource_id(),
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
,
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
,
2352 google_apis::test_util::GetTestFilePath(
2353 "gdata/root_feed.json"),
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
,
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
,
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/"),
2431 dirty_cache_file_path
,
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
,
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
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", _
, _
))
2501 const SearchResultPair kExpectedResults
[] = {
2502 { "drive/Directory 1/SubDirectory File 1.txt", false },
2503 { "drive/Directory 1", true }
2506 SearchCallback callback
= base::Bind(&DriveSearchCallback
,
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", _
, _
))
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()), _
, "", _
, _
))
2541 EXPECT_CALL(*mock_webapps_registry_
, UpdateFromFeed(_
)).Times(1);
2543 SearchCallback callback
= base::Bind(&DriveSearchCallback
,
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", _
, _
))
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
, _
))
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
))
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
,
2640 GURL("https://file_content_url_changed/"),
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();
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
,
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
,
2682 // Try to close the same file twice.
2683 file_system_
->CloseFile(kFileInRoot
, close_file_callback
);
2684 message_loop_
.Run();
2687 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND
, callback_helper_
->last_error_
);
2690 } // namespace drive