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/file_system.h"
10 #include "base/bind.h"
11 #include "base/file_util.h"
12 #include "base/files/file_path.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/prefs/testing_pref_service.h"
17 #include "base/run_loop.h"
18 #include "chrome/browser/chromeos/drive/change_list_loader.h"
19 #include "chrome/browser/chromeos/drive/drive.pb.h"
20 #include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
21 #include "chrome/browser/chromeos/drive/file_system_observer.h"
22 #include "chrome/browser/chromeos/drive/file_system_util.h"
23 #include "chrome/browser/chromeos/drive/job_scheduler.h"
24 #include "chrome/browser/chromeos/drive/sync_client.h"
25 #include "chrome/browser/chromeos/drive/test_util.h"
26 #include "chrome/browser/drive/event_logger.h"
27 #include "chrome/browser/drive/fake_drive_service.h"
28 #include "content/public/test/test_browser_thread_bundle.h"
29 #include "google_apis/drive/drive_api_parser.h"
30 #include "google_apis/drive/test_util.h"
31 #include "testing/gtest/include/gtest/gtest.h"
36 // Counts the number of invocation, and if it increased up to |expected_counter|
37 // quits the current message loop by calling |quit|.
38 void AsyncInitializationCallback(
39 int* counter, int expected_counter, const base::Closure& quit,
40 FileError error, scoped_ptr<ResourceEntry> entry) {
41 if (error != FILE_ERROR_OK || !entry) {
42 // If we hit an error case, quit the message loop immediately.
43 // Then the expectation in the test case can find it because the actual
44 // value of |counter| is different from the expected one.
50 if (*counter >= expected_counter)
54 // This class is used to record directory changes and examine them later.
55 class MockDirectoryChangeObserver : public FileSystemObserver {
57 MockDirectoryChangeObserver() {}
58 virtual ~MockDirectoryChangeObserver() {}
60 // FileSystemObserver overrides.
61 virtual void OnDirectoryChanged(
62 const base::FilePath& directory_path) OVERRIDE {
63 changed_directories_.push_back(directory_path);
66 const std::vector<base::FilePath>& changed_directories() const {
67 return changed_directories_;
71 std::vector<base::FilePath> changed_directories_;
72 DISALLOW_COPY_AND_ASSIGN(MockDirectoryChangeObserver);
77 class FileSystemTest : public testing::Test {
79 virtual void SetUp() OVERRIDE {
80 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
81 pref_service_.reset(new TestingPrefServiceSimple);
82 test_util::RegisterDrivePrefs(pref_service_->registry());
84 logger_.reset(new EventLogger);
85 fake_drive_service_.reset(new FakeDriveService);
86 fake_drive_service_->LoadResourceListForWapi(
87 "gdata/root_feed.json");
88 fake_drive_service_->LoadAccountMetadataForWapi(
89 "gdata/account_metadata.json");
91 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
93 scheduler_.reset(new JobScheduler(pref_service_.get(),
95 fake_drive_service_.get(),
96 base::MessageLoopProxy::current().get()));
98 mock_directory_observer_.reset(new MockDirectoryChangeObserver);
100 SetUpResourceMetadataAndFileSystem();
103 void SetUpResourceMetadataAndFileSystem() {
104 const base::FilePath metadata_dir = temp_dir_.path().AppendASCII("meta");
105 ASSERT_TRUE(base::CreateDirectory(metadata_dir));
106 metadata_storage_.reset(new internal::ResourceMetadataStorage(
107 metadata_dir, base::MessageLoopProxy::current().get()));
108 ASSERT_TRUE(metadata_storage_->Initialize());
110 const base::FilePath cache_dir = temp_dir_.path().AppendASCII("files");
111 ASSERT_TRUE(base::CreateDirectory(cache_dir));
112 cache_.reset(new internal::FileCache(
113 metadata_storage_.get(),
115 base::MessageLoopProxy::current().get(),
116 fake_free_disk_space_getter_.get()));
117 ASSERT_TRUE(cache_->Initialize());
119 resource_metadata_.reset(new internal::ResourceMetadata(
120 metadata_storage_.get(), base::MessageLoopProxy::current()));
121 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
123 const base::FilePath temp_file_dir = temp_dir_.path().AppendASCII("tmp");
124 ASSERT_TRUE(base::CreateDirectory(temp_file_dir));
125 file_system_.reset(new FileSystem(
129 fake_drive_service_.get(),
131 resource_metadata_.get(),
132 base::MessageLoopProxy::current().get(),
134 file_system_->AddObserver(mock_directory_observer_.get());
136 // Disable delaying so that the sync starts immediately.
137 file_system_->sync_client_for_testing()->set_delay_for_testing(
138 base::TimeDelta::FromSeconds(0));
141 // Loads the full resource list via FakeDriveService.
142 bool LoadFullResourceList() {
143 FileError error = FILE_ERROR_FAILED;
144 file_system_->change_list_loader_for_testing()->LoadForTesting(
145 google_apis::test_util::CreateCopyResultCallback(&error));
146 test_util::RunBlockingPoolTask();
147 return error == FILE_ERROR_OK;
150 // Gets resource entry by path synchronously.
151 scoped_ptr<ResourceEntry> GetResourceEntrySync(
152 const base::FilePath& file_path) {
153 FileError error = FILE_ERROR_FAILED;
154 scoped_ptr<ResourceEntry> entry;
155 file_system_->GetResourceEntry(
157 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
158 test_util::RunBlockingPoolTask();
163 // Gets directory info by path synchronously.
164 scoped_ptr<ResourceEntryVector> ReadDirectorySync(
165 const base::FilePath& file_path) {
166 FileError error = FILE_ERROR_FAILED;
167 scoped_ptr<ResourceEntryVector> entries(new ResourceEntryVector);
168 bool last_has_more = true;
169 file_system_->ReadDirectory(
171 base::Bind(&AccumulateReadDirectoryResult,
172 &error, entries.get(), &last_has_more));
173 test_util::RunBlockingPoolTask();
174 if (error != FILE_ERROR_OK)
176 return entries.Pass();
179 // Used to implement ReadDirectorySync().
180 static void AccumulateReadDirectoryResult(
181 FileError* out_error,
182 ResourceEntryVector* out_entries,
185 scoped_ptr<ResourceEntryVector> entries,
187 EXPECT_TRUE(*last_has_more);
189 *last_has_more = has_more;
190 if (error == FILE_ERROR_OK) {
191 ASSERT_TRUE(entries);
192 out_entries->insert(out_entries->end(), entries->begin(), entries->end());
194 EXPECT_FALSE(has_more);
198 // Returns true if an entry exists at |file_path|.
199 bool EntryExists(const base::FilePath& file_path) {
200 return GetResourceEntrySync(file_path);
203 // Flag for specifying the timestamp of the test filesystem cache.
204 enum SetUpTestFileSystemParam {
206 USE_SERVER_TIMESTAMP,
209 // Sets up a filesystem with directories: drive/root, drive/root/Dir1,
210 // drive/root/Dir1/SubDir2 and files drive/root/File1, drive/root/Dir1/File2,
211 // drive/root/Dir1/SubDir2/File3. If |use_up_to_date_timestamp| is true, sets
212 // the changestamp to 654321, equal to that of "account_metadata.json" test
213 // data, indicating the cache is holding the latest file system info.
214 void SetUpTestFileSystem(SetUpTestFileSystemParam param) {
215 // Destroy the existing resource metadata to close DB.
216 resource_metadata_.reset();
218 const base::FilePath metadata_dir = temp_dir_.path().AppendASCII("meta");
219 ASSERT_TRUE(base::CreateDirectory(metadata_dir));
220 scoped_ptr<internal::ResourceMetadataStorage,
221 test_util::DestroyHelperForTests> metadata_storage(
222 new internal::ResourceMetadataStorage(
223 metadata_dir, base::MessageLoopProxy::current().get()));
225 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
226 resource_metadata(new internal::ResourceMetadata(
227 metadata_storage_.get(), base::MessageLoopProxy::current()));
229 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->Initialize());
231 const int64 changestamp = param == USE_SERVER_TIMESTAMP ? 654321 : 1;
232 ASSERT_EQ(FILE_ERROR_OK,
233 resource_metadata->SetLargestChangestamp(changestamp));
237 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->GetResourceEntryByPath(
238 util::GetDriveMyDriveRootPath(), &root));
239 root.set_resource_id(fake_drive_service_->GetRootResourceId());
240 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->RefreshEntry(root));
242 std::string local_id;
246 file1.set_title("File1");
247 file1.set_resource_id("resource_id:File1");
248 file1.set_parent_local_id(root.local_id());
249 file1.mutable_file_specific_info()->set_md5("md5");
250 file1.mutable_file_info()->set_is_directory(false);
251 file1.mutable_file_info()->set_size(1048576);
252 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file1, &local_id));
256 dir1.set_title("Dir1");
257 dir1.set_resource_id("resource_id:Dir1");
258 dir1.set_parent_local_id(root.local_id());
259 dir1.mutable_file_info()->set_is_directory(true);
260 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(dir1, &local_id));
261 const std::string dir1_local_id = local_id;
263 // drive/root/Dir1/File2
265 file2.set_title("File2");
266 file2.set_resource_id("resource_id:File2");
267 file2.set_parent_local_id(dir1_local_id);
268 file2.mutable_file_specific_info()->set_md5("md5");
269 file2.mutable_file_info()->set_is_directory(false);
270 file2.mutable_file_info()->set_size(555);
271 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file2, &local_id));
273 // drive/root/Dir1/SubDir2
275 dir2.set_title("SubDir2");
276 dir2.set_resource_id("resource_id:SubDir2");
277 dir2.set_parent_local_id(dir1_local_id);
278 dir2.mutable_file_info()->set_is_directory(true);
279 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(dir2, &local_id));
280 const std::string dir2_local_id = local_id;
282 // drive/root/Dir1/SubDir2/File3
284 file3.set_title("File3");
285 file3.set_resource_id("resource_id:File3");
286 file3.set_parent_local_id(dir2_local_id);
287 file3.mutable_file_specific_info()->set_md5("md5");
288 file3.mutable_file_info()->set_is_directory(false);
289 file3.mutable_file_info()->set_size(12345);
290 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file3, &local_id));
292 // Recreate resource metadata.
293 SetUpResourceMetadataAndFileSystem();
296 content::TestBrowserThreadBundle thread_bundle_;
297 base::ScopedTempDir temp_dir_;
298 // We don't use TestingProfile::GetPrefs() in favor of having less
299 // dependencies to Profile in general.
300 scoped_ptr<TestingPrefServiceSimple> pref_service_;
302 scoped_ptr<EventLogger> logger_;
303 scoped_ptr<FakeDriveService> fake_drive_service_;
304 scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
305 scoped_ptr<JobScheduler> scheduler_;
306 scoped_ptr<MockDirectoryChangeObserver> mock_directory_observer_;
308 scoped_ptr<internal::ResourceMetadataStorage,
309 test_util::DestroyHelperForTests> metadata_storage_;
310 scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache_;
311 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
313 scoped_ptr<FileSystem> file_system_;
316 TEST_F(FileSystemTest, DuplicatedAsyncInitialization) {
320 const GetResourceEntryCallback& callback = base::Bind(
321 &AsyncInitializationCallback, &counter, 2, loop.QuitClosure());
323 file_system_->GetResourceEntry(
324 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback);
325 file_system_->GetResourceEntry(
326 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback);
327 loop.Run(); // Wait to get our result
328 EXPECT_EQ(2, counter);
330 EXPECT_EQ(1, fake_drive_service_->resource_list_load_count());
333 TEST_F(FileSystemTest, GetGrandRootEntry) {
334 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive"));
335 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
337 EXPECT_EQ(util::kDriveGrandRootLocalId, entry->local_id());
340 TEST_F(FileSystemTest, GetOtherDirEntry) {
341 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/other"));
342 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
344 EXPECT_EQ(util::kDriveOtherDirLocalId, entry->local_id());
347 TEST_F(FileSystemTest, GetMyDriveRoot) {
348 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root"));
349 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
351 EXPECT_EQ(fake_drive_service_->GetRootResourceId(), entry->resource_id());
353 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
355 // After "fast fetch" is done, full resource list is fetched.
356 EXPECT_EQ(1, fake_drive_service_->resource_list_load_count());
359 TEST_F(FileSystemTest, GetExistingFile) {
360 // Simulate the situation that full feed fetching takes very long time,
361 // to test the recursive "fast fetch" feature is properly working.
362 fake_drive_service_->set_never_return_all_resource_list(true);
364 const base::FilePath kFilePath(
365 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
366 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
368 EXPECT_EQ("file:subdirectory_file_1_id", entry->resource_id());
370 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
371 EXPECT_EQ(2, fake_drive_service_->directory_load_count());
372 EXPECT_EQ(1, fake_drive_service_->blocked_resource_list_load_count());
375 TEST_F(FileSystemTest, GetExistingDocument) {
376 const base::FilePath kFilePath(
377 FILE_PATH_LITERAL("drive/root/Document 1 excludeDir-test.gdoc"));
378 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
380 EXPECT_EQ("document:5_document_resource_id", entry->resource_id());
383 TEST_F(FileSystemTest, GetNonExistingFile) {
384 const base::FilePath kFilePath(
385 FILE_PATH_LITERAL("drive/root/nonexisting.file"));
386 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
390 TEST_F(FileSystemTest, GetExistingDirectory) {
391 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/Directory 1"));
392 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
394 ASSERT_EQ("folder:1_folder_resource_id", entry->resource_id());
396 // The changestamp should be propagated to the directory.
397 EXPECT_EQ(fake_drive_service_->about_resource().largest_change_id(),
398 entry->directory_specific_info().changestamp());
401 TEST_F(FileSystemTest, GetInSubSubdir) {
402 const base::FilePath kFilePath(
403 FILE_PATH_LITERAL("drive/root/Directory 1/Sub Directory Folder/"
404 "Sub Sub Directory Folder"));
405 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
407 ASSERT_EQ("folder:sub_sub_directory_folder_id", entry->resource_id());
410 TEST_F(FileSystemTest, GetOrphanFile) {
411 ASSERT_TRUE(LoadFullResourceList());
413 // Entry without parents are placed under "drive/other".
414 const base::FilePath kFilePath(
415 FILE_PATH_LITERAL("drive/other/Orphan File 1.txt"));
416 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
418 EXPECT_EQ("file:1_orphanfile_resource_id", entry->resource_id());
421 TEST_F(FileSystemTest, ReadDirectory_Root) {
422 // ReadDirectory() should kick off the resource list loading.
423 scoped_ptr<ResourceEntryVector> entries(
424 ReadDirectorySync(base::FilePath::FromUTF8Unsafe("drive")));
425 // The root directory should be read correctly.
426 ASSERT_TRUE(entries);
427 ASSERT_EQ(3U, entries->size());
429 // The found three directories should be /drive/root, /drive/other and
431 std::set<base::FilePath> found;
432 for (size_t i = 0; i < entries->size(); ++i)
433 found.insert(base::FilePath::FromUTF8Unsafe((*entries)[i].title()));
434 EXPECT_EQ(3U, found.size());
435 EXPECT_EQ(1U, found.count(base::FilePath(util::kDriveMyDriveRootDirName)));
436 EXPECT_EQ(1U, found.count(base::FilePath(util::kDriveOtherDirName)));
437 EXPECT_EQ(1U, found.count(base::FilePath(util::kDriveTrashDirName)));
440 TEST_F(FileSystemTest, ReadDirectory_NonRootDirectory) {
441 // ReadDirectory() should kick off the resource list loading.
442 scoped_ptr<ResourceEntryVector> entries(
444 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
445 // The non root directory should also be read correctly.
446 // There was a bug (crbug.com/181487), which broke this behavior.
447 // Make sure this is fixed.
448 ASSERT_TRUE(entries);
449 EXPECT_EQ(3U, entries->size());
452 TEST_F(FileSystemTest, LoadFileSystemFromUpToDateCache) {
453 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP));
455 // Kicks loading of cached file system and query for server update.
456 EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
458 // SetUpTestFileSystem and "account_metadata.json" have the same
459 // changestamp (i.e. the local metadata is up-to-date), so no request for
460 // new resource list (i.e., call to GetResourceList) should happen.
461 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
462 EXPECT_EQ(0, fake_drive_service_->resource_list_load_count());
464 // Since the file system has verified that it holds the latest snapshot,
465 // it should change its state to "loaded", which admits periodic refresh.
466 // To test it, call CheckForUpdates and verify it does try to check updates.
467 file_system_->CheckForUpdates();
468 test_util::RunBlockingPoolTask();
469 EXPECT_EQ(2, fake_drive_service_->about_resource_load_count());
472 TEST_F(FileSystemTest, LoadFileSystemFromCacheWhileOffline) {
473 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
475 // Make GetResourceList fail for simulating offline situation. This will
476 // leave the file system "loaded from cache, but not synced with server"
478 fake_drive_service_->set_offline(true);
481 EXPECT_TRUE(ReadDirectorySync(util::GetDriveGrandRootPath()));
482 // Loading of about resource should not happen as it's offline.
483 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
486 EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
487 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
489 // Tests that cached data can be loaded even if the server is not reachable.
490 EXPECT_TRUE(EntryExists(base::FilePath(
491 FILE_PATH_LITERAL("drive/root/File1"))));
492 EXPECT_TRUE(EntryExists(base::FilePath(
493 FILE_PATH_LITERAL("drive/root/Dir1"))));
494 EXPECT_TRUE(EntryExists(base::FilePath(
495 FILE_PATH_LITERAL("drive/root/Dir1/File2"))));
496 EXPECT_TRUE(EntryExists(base::FilePath(
497 FILE_PATH_LITERAL("drive/root/Dir1/SubDir2"))));
498 EXPECT_TRUE(EntryExists(base::FilePath(
499 FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"))));
501 // Since the file system has at least succeeded to load cached snapshot,
502 // the file system should be able to start periodic refresh.
503 // To test it, call CheckForUpdates and verify it does try to check
504 // updates, which will cause directory changes.
505 fake_drive_service_->set_offline(false);
507 file_system_->CheckForUpdates();
509 test_util::RunBlockingPoolTask();
510 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
511 EXPECT_EQ(1, fake_drive_service_->change_list_load_count());
513 ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
516 TEST_F(FileSystemTest, ReadDirectoryWhileRefreshing) {
517 // Enter the "refreshing" state so the fast fetch will be performed.
518 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
519 file_system_->CheckForUpdates();
521 // The list of resources in "drive/root/Dir1" should be fetched.
522 EXPECT_TRUE(ReadDirectorySync(base::FilePath(
523 FILE_PATH_LITERAL("drive/root/Dir1"))));
524 EXPECT_EQ(1, fake_drive_service_->directory_load_count());
526 ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
529 TEST_F(FileSystemTest, GetResourceEntryNonExistentWhileRefreshing) {
530 // Enter the "refreshing" state so the fast fetch will be performed.
531 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
532 file_system_->CheckForUpdates();
534 // If an entry is not found, parent directory's resource list is fetched.
535 EXPECT_FALSE(GetResourceEntrySync(base::FilePath(
536 FILE_PATH_LITERAL("drive/root/Dir1/NonExistentFile"))));
537 EXPECT_EQ(1, fake_drive_service_->directory_load_count());
539 ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
542 TEST_F(FileSystemTest, CreateDirectoryByImplicitLoad) {
543 // Intentionally *not* calling LoadFullResourceList(), for testing that
544 // CreateDirectory ensures the resource list is loaded before it runs.
546 base::FilePath existing_directory(
547 FILE_PATH_LITERAL("drive/root/Directory 1"));
548 FileError error = FILE_ERROR_FAILED;
549 file_system_->CreateDirectory(
551 true, // is_exclusive
552 false, // is_recursive
553 google_apis::test_util::CreateCopyResultCallback(&error));
554 test_util::RunBlockingPoolTask();
556 // It should fail because is_exclusive is set to true.
557 EXPECT_EQ(FILE_ERROR_EXISTS, error);
560 TEST_F(FileSystemTest, CreateDirectoryRecursively) {
561 // Intentionally *not* calling LoadFullResourceList(), for testing that
562 // CreateDirectory ensures the resource list is loaded before it runs.
564 base::FilePath new_directory(
565 FILE_PATH_LITERAL("drive/root/Directory 1/a/b/c/d"));
566 FileError error = FILE_ERROR_FAILED;
567 file_system_->CreateDirectory(
569 true, // is_exclusive
570 true, // is_recursive
571 google_apis::test_util::CreateCopyResultCallback(&error));
572 test_util::RunBlockingPoolTask();
574 EXPECT_EQ(FILE_ERROR_OK, error);
576 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(new_directory));
578 EXPECT_TRUE(entry->file_info().is_directory());
581 TEST_F(FileSystemTest, PinAndUnpin) {
582 ASSERT_TRUE(LoadFullResourceList());
584 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
586 // Get the file info.
587 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
591 FileError error = FILE_ERROR_FAILED;
592 file_system_->Pin(file_path,
593 google_apis::test_util::CreateCopyResultCallback(&error));
594 test_util::RunBlockingPoolTask();
595 EXPECT_EQ(FILE_ERROR_OK, error);
597 FileCacheEntry cache_entry;
598 EXPECT_TRUE(cache_->GetCacheEntry(entry->local_id(), &cache_entry));
599 EXPECT_TRUE(cache_entry.is_pinned());
600 EXPECT_TRUE(cache_entry.is_present());
603 error = FILE_ERROR_FAILED;
604 file_system_->Unpin(file_path,
605 google_apis::test_util::CreateCopyResultCallback(&error));
606 test_util::RunBlockingPoolTask();
607 EXPECT_EQ(FILE_ERROR_OK, error);
609 EXPECT_TRUE(cache_->GetCacheEntry(entry->local_id(), &cache_entry));
610 EXPECT_FALSE(cache_entry.is_pinned());
612 // Pinned file gets synced and it results in entry state changes.
613 ASSERT_EQ(1u, mock_directory_observer_->changed_directories().size());
614 EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("drive/root")),
615 mock_directory_observer_->changed_directories()[0]);
618 TEST_F(FileSystemTest, PinAndUnpin_NotSynced) {
619 ASSERT_TRUE(LoadFullResourceList());
621 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
623 // Get the file info.
624 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
627 // Unpin the file just after pinning. File fetch should be cancelled.
628 FileError error_pin = FILE_ERROR_FAILED;
631 google_apis::test_util::CreateCopyResultCallback(&error_pin));
633 FileError error_unpin = FILE_ERROR_FAILED;
636 google_apis::test_util::CreateCopyResultCallback(&error_unpin));
638 test_util::RunBlockingPoolTask();
639 EXPECT_EQ(FILE_ERROR_OK, error_pin);
640 EXPECT_EQ(FILE_ERROR_OK, error_unpin);
642 // No cache file available because the sync was cancelled by Unpin().
643 FileCacheEntry cache_entry;
644 EXPECT_FALSE(cache_->GetCacheEntry(entry->local_id(), &cache_entry));
647 TEST_F(FileSystemTest, GetAvailableSpace) {
648 FileError error = FILE_ERROR_OK;
651 file_system_->GetAvailableSpace(
652 google_apis::test_util::CreateCopyResultCallback(
653 &error, &bytes_total, &bytes_used));
654 test_util::RunBlockingPoolTask();
655 EXPECT_EQ(GG_LONGLONG(6789012345), bytes_used);
656 EXPECT_EQ(GG_LONGLONG(9876543210), bytes_total);
659 TEST_F(FileSystemTest, MarkCacheFileAsMountedAndUnmounted) {
660 ASSERT_TRUE(LoadFullResourceList());
662 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
663 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_in_root));
667 ASSERT_EQ(FILE_ERROR_OK, cache_->Store(
669 entry->file_specific_info().md5(),
670 google_apis::test_util::GetTestFilePath("gdata/root_feed.json"),
671 internal::FileCache::FILE_OPERATION_COPY));
673 // Test for mounting.
674 FileError error = FILE_ERROR_FAILED;
675 base::FilePath file_path;
676 file_system_->MarkCacheFileAsMounted(
678 google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
679 test_util::RunBlockingPoolTask();
680 EXPECT_EQ(FILE_ERROR_OK, error);
682 // Cannot remove a cache entry while it's being mounted.
683 EXPECT_EQ(FILE_ERROR_IN_USE, cache_->Remove(entry->local_id()));
685 // Test for unmounting.
686 error = FILE_ERROR_FAILED;
687 file_system_->MarkCacheFileAsUnmounted(
689 google_apis::test_util::CreateCopyResultCallback(&error));
690 test_util::RunBlockingPoolTask();
691 EXPECT_EQ(FILE_ERROR_OK, error);
693 // Now able to remove the cache entry.
694 EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(entry->local_id()));
697 TEST_F(FileSystemTest, GetShareUrl) {
698 ASSERT_TRUE(LoadFullResourceList());
700 const base::FilePath kFileInRoot(FILE_PATH_LITERAL("drive/root/File 1.txt"));
701 const GURL kEmbedOrigin("chrome-extension://test-id");
703 // Try to fetch the URL for the sharing dialog.
704 FileError error = FILE_ERROR_FAILED;
706 file_system_->GetShareUrl(
709 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
710 test_util::RunBlockingPoolTask();
712 // Verify the share url to the sharing dialog.
713 EXPECT_EQ(FILE_ERROR_OK, error);
714 EXPECT_EQ(GURL("https://file_link_share/"), share_url);
717 TEST_F(FileSystemTest, GetShareUrlNotAvailable) {
718 ASSERT_TRUE(LoadFullResourceList());
720 const base::FilePath kFileInRoot(
721 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
722 const GURL kEmbedOrigin("chrome-extension://test-id");
724 // Try to fetch the URL for the sharing dialog.
725 FileError error = FILE_ERROR_FAILED;
728 file_system_->GetShareUrl(
731 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
732 test_util::RunBlockingPoolTask();
734 // Verify the error and the share url, which should be empty.
735 EXPECT_EQ(FILE_ERROR_FAILED, error);
736 EXPECT_TRUE(share_url.is_empty());