Roll src/third_party/WebKit 9f7fb92:f103b33 (svn 202621:202622)
[chromium-blink-merge.git] / components / drive / file_system_unittest.cc
bloba502a2a55c135d8b7722aa07c7544723946065b9
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 "components/drive/file_system.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/prefs/testing_pref_service.h"
16 #include "base/run_loop.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "components/drive/change_list_loader.h"
20 #include "components/drive/drive.pb.h"
21 #include "components/drive/drive_api_util.h"
22 #include "components/drive/drive_test_util.h"
23 #include "components/drive/event_logger.h"
24 #include "components/drive/fake_free_disk_space_getter.h"
25 #include "components/drive/file_change.h"
26 #include "components/drive/file_system_core_util.h"
27 #include "components/drive/file_system_observer.h"
28 #include "components/drive/job_scheduler.h"
29 #include "components/drive/service/fake_drive_service.h"
30 #include "components/drive/service/test_util.h"
31 #include "components/drive/sync_client.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "content/public/test/test_browser_thread_bundle.h"
34 #include "google_apis/drive/drive_api_parser.h"
35 #include "google_apis/drive/test_util.h"
36 #include "testing/gtest/include/gtest/gtest.h"
38 namespace drive {
39 namespace {
41 // Counts the number of invocation, and if it increased up to |expected_counter|
42 // quits the current message loop by calling |quit|.
43 void AsyncInitializationCallback(
44 int* counter, int expected_counter, const base::Closure& quit,
45 FileError error, scoped_ptr<ResourceEntry> entry) {
46 if (error != FILE_ERROR_OK || !entry) {
47 // If we hit an error case, quit the message loop immediately.
48 // Then the expectation in the test case can find it because the actual
49 // value of |counter| is different from the expected one.
50 quit.Run();
51 return;
54 (*counter)++;
55 if (*counter >= expected_counter)
56 quit.Run();
59 bool CompareHashAndFilePath(const HashAndFilePath& a,
60 const HashAndFilePath& b) {
61 const int result = a.hash.compare(b.hash);
62 if (result < 0)
63 return true;
64 if (result > 0)
65 return false;
66 return a.path.AsUTF8Unsafe().compare(b.path.AsUTF8Unsafe()) < 0;
69 // This class is used to record directory changes and examine them later.
70 class MockDirectoryChangeObserver : public FileSystemObserver {
71 public:
72 MockDirectoryChangeObserver() {}
73 ~MockDirectoryChangeObserver() override {}
75 // FileSystemObserver overrides.
76 void OnDirectoryChanged(const base::FilePath& directory_path) override {
77 changed_directories_.push_back(directory_path);
80 void OnFileChanged(const FileChange& new_file_change) override {
81 changed_files_.Apply(new_file_change);
84 const std::vector<base::FilePath>& changed_directories() const {
85 return changed_directories_;
88 const FileChange& changed_files() const { return changed_files_; }
90 private:
91 std::vector<base::FilePath> changed_directories_;
92 FileChange changed_files_;
93 DISALLOW_COPY_AND_ASSIGN(MockDirectoryChangeObserver);
96 } // namespace
98 class FileSystemTest : public testing::Test {
99 protected:
100 void SetUp() override {
101 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
102 pref_service_.reset(new TestingPrefServiceSimple);
103 test_util::RegisterDrivePrefs(pref_service_->registry());
105 logger_.reset(new EventLogger);
106 fake_drive_service_.reset(new FakeDriveService);
107 test_util::SetUpTestEntries(fake_drive_service_.get());
109 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
111 scheduler_.reset(new JobScheduler(
112 pref_service_.get(),
113 logger_.get(),
114 fake_drive_service_.get(),
115 base::ThreadTaskRunnerHandle::Get().get()));
117 mock_directory_observer_.reset(new MockDirectoryChangeObserver);
119 SetUpResourceMetadataAndFileSystem();
122 void SetUpResourceMetadataAndFileSystem() {
123 const base::FilePath metadata_dir = temp_dir_.path().AppendASCII("meta");
124 ASSERT_TRUE(base::CreateDirectory(metadata_dir));
125 metadata_storage_.reset(new internal::ResourceMetadataStorage(
126 metadata_dir, base::ThreadTaskRunnerHandle::Get().get()));
127 ASSERT_TRUE(metadata_storage_->Initialize());
129 const base::FilePath cache_dir = temp_dir_.path().AppendASCII("files");
130 ASSERT_TRUE(base::CreateDirectory(cache_dir));
131 cache_.reset(new internal::FileCache(
132 metadata_storage_.get(),
133 cache_dir,
134 base::ThreadTaskRunnerHandle::Get().get(),
135 fake_free_disk_space_getter_.get()));
136 ASSERT_TRUE(cache_->Initialize());
138 resource_metadata_.reset(new internal::ResourceMetadata(
139 metadata_storage_.get(), cache_.get(),
140 base::ThreadTaskRunnerHandle::Get()));
141 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
143 const base::FilePath temp_file_dir = temp_dir_.path().AppendASCII("tmp");
144 ASSERT_TRUE(base::CreateDirectory(temp_file_dir));
145 file_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
146 content::BrowserThread::FILE);
147 file_system_.reset(new FileSystem(
148 pref_service_.get(), logger_.get(), cache_.get(), scheduler_.get(),
149 resource_metadata_.get(), base::ThreadTaskRunnerHandle::Get().get(),
150 file_task_runner_.get(), temp_file_dir));
151 file_system_->AddObserver(mock_directory_observer_.get());
153 // Disable delaying so that the sync starts immediately.
154 file_system_->sync_client_for_testing()->set_delay_for_testing(
155 base::TimeDelta::FromSeconds(0));
158 // Loads the full resource list via FakeDriveService.
159 bool LoadFullResourceList() {
160 FileError error = FILE_ERROR_FAILED;
161 file_system_->change_list_loader_for_testing()->LoadIfNeeded(
162 google_apis::test_util::CreateCopyResultCallback(&error));
163 content::RunAllBlockingPoolTasksUntilIdle();
164 return error == FILE_ERROR_OK;
167 // Gets resource entry by path synchronously.
168 scoped_ptr<ResourceEntry> GetResourceEntrySync(
169 const base::FilePath& file_path) {
170 FileError error = FILE_ERROR_FAILED;
171 scoped_ptr<ResourceEntry> entry;
172 file_system_->GetResourceEntry(
173 file_path,
174 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
175 content::RunAllBlockingPoolTasksUntilIdle();
177 return entry.Pass();
180 // Gets directory info by path synchronously.
181 scoped_ptr<ResourceEntryVector> ReadDirectorySync(
182 const base::FilePath& file_path) {
183 FileError error = FILE_ERROR_FAILED;
184 scoped_ptr<ResourceEntryVector> entries(new ResourceEntryVector);
185 file_system_->ReadDirectory(
186 file_path,
187 base::Bind(&AccumulateReadDirectoryResult, entries.get()),
188 google_apis::test_util::CreateCopyResultCallback(&error));
189 content::RunAllBlockingPoolTasksUntilIdle();
190 if (error != FILE_ERROR_OK)
191 entries.reset();
192 return entries.Pass();
195 // Used to implement ReadDirectorySync().
196 static void AccumulateReadDirectoryResult(
197 ResourceEntryVector* out_entries,
198 scoped_ptr<ResourceEntryVector> entries) {
199 ASSERT_TRUE(entries);
200 out_entries->insert(out_entries->end(), entries->begin(), entries->end());
203 // Returns true if an entry exists at |file_path|.
204 bool EntryExists(const base::FilePath& file_path) {
205 return GetResourceEntrySync(file_path);
208 // Flag for specifying the timestamp of the test filesystem cache.
209 enum SetUpTestFileSystemParam {
210 USE_OLD_TIMESTAMP,
211 USE_SERVER_TIMESTAMP,
214 // Sets up a filesystem with directories: drive/root, drive/root/Dir1,
215 // drive/root/Dir1/SubDir2 and files drive/root/File1, drive/root/Dir1/File2,
216 // drive/root/Dir1/SubDir2/File3. If |use_up_to_date_timestamp| is true, sets
217 // the changestamp to that of FakeDriveService, indicating the cache is
218 // holding the latest file system info.
219 void SetUpTestFileSystem(SetUpTestFileSystemParam param) {
220 // Destroy the existing resource metadata to close DB.
221 resource_metadata_.reset();
223 const base::FilePath metadata_dir = temp_dir_.path().AppendASCII("meta");
224 ASSERT_TRUE(base::CreateDirectory(metadata_dir));
225 scoped_ptr<internal::ResourceMetadataStorage,
226 test_util::DestroyHelperForTests> metadata_storage(
227 new internal::ResourceMetadataStorage(
228 metadata_dir, base::ThreadTaskRunnerHandle::Get().get()));
230 const base::FilePath cache_dir = temp_dir_.path().AppendASCII("files");
231 scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache(
232 new internal::FileCache(metadata_storage.get(),
233 cache_dir,
234 base::ThreadTaskRunnerHandle::Get().get(),
235 fake_free_disk_space_getter_.get()));
237 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
238 resource_metadata(new internal::ResourceMetadata(
239 metadata_storage_.get(), cache.get(),
240 base::ThreadTaskRunnerHandle::Get()));
242 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->Initialize());
244 const int64 changestamp = param == USE_SERVER_TIMESTAMP ?
245 fake_drive_service_->about_resource().largest_change_id() : 1;
246 ASSERT_EQ(FILE_ERROR_OK,
247 resource_metadata->SetLargestChangestamp(changestamp));
249 // drive/root
250 ResourceEntry root;
251 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->GetResourceEntryByPath(
252 util::GetDriveMyDriveRootPath(), &root));
253 root.set_resource_id(fake_drive_service_->GetRootResourceId());
254 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->RefreshEntry(root));
256 std::string local_id;
258 // drive/root/File1
259 ResourceEntry file1;
260 file1.set_title("File1");
261 file1.set_resource_id("resource_id:File1");
262 file1.set_parent_local_id(root.local_id());
263 file1.mutable_file_specific_info()->set_md5("md5#1");
264 file1.mutable_file_info()->set_is_directory(false);
265 file1.mutable_file_info()->set_size(1048576);
266 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file1, &local_id));
268 // drive/root/Dir1
269 ResourceEntry dir1;
270 dir1.set_title("Dir1");
271 dir1.set_resource_id("resource_id:Dir1");
272 dir1.set_parent_local_id(root.local_id());
273 dir1.mutable_file_info()->set_is_directory(true);
274 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(dir1, &local_id));
275 const std::string dir1_local_id = local_id;
277 // drive/root/Dir1/File2
278 ResourceEntry file2;
279 file2.set_title("File2");
280 file2.set_resource_id("resource_id:File2");
281 file2.set_parent_local_id(dir1_local_id);
282 file2.mutable_file_specific_info()->set_md5("md5#2");
283 file2.mutable_file_info()->set_is_directory(false);
284 file2.mutable_file_info()->set_size(555);
285 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file2, &local_id));
287 // drive/root/Dir1/SubDir2
288 ResourceEntry dir2;
289 dir2.set_title("SubDir2");
290 dir2.set_resource_id("resource_id:SubDir2");
291 dir2.set_parent_local_id(dir1_local_id);
292 dir2.mutable_file_info()->set_is_directory(true);
293 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(dir2, &local_id));
294 const std::string dir2_local_id = local_id;
296 // drive/root/Dir1/SubDir2/File3
297 ResourceEntry file3;
298 file3.set_title("File3");
299 file3.set_resource_id("resource_id:File3");
300 file3.set_parent_local_id(dir2_local_id);
301 file3.mutable_file_specific_info()->set_md5("md5#2");
302 file3.mutable_file_info()->set_is_directory(false);
303 file3.mutable_file_info()->set_size(12345);
304 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file3, &local_id));
306 // Recreate resource metadata.
307 SetUpResourceMetadataAndFileSystem();
310 content::TestBrowserThreadBundle thread_bundle_;
311 base::ScopedTempDir temp_dir_;
312 // We don't use TestingProfile::GetPrefs() in favor of having less
313 // dependencies to Profile in general.
314 scoped_ptr<TestingPrefServiceSimple> pref_service_;
316 scoped_ptr<EventLogger> logger_;
317 scoped_ptr<FakeDriveService> fake_drive_service_;
318 scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
319 scoped_ptr<JobScheduler> scheduler_;
320 scoped_ptr<MockDirectoryChangeObserver> mock_directory_observer_;
322 scoped_ptr<internal::ResourceMetadataStorage,
323 test_util::DestroyHelperForTests> metadata_storage_;
324 scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache_;
325 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
326 resource_metadata_;
327 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
328 scoped_ptr<FileSystem> file_system_;
331 TEST_F(FileSystemTest, SearchByHashes) {
332 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP));
334 std::set<std::string> hashes;
335 FileError error;
336 std::vector<HashAndFilePath> results;
338 hashes.insert("md5#1");
339 file_system_->SearchByHashes(
340 hashes,
341 google_apis::test_util::CreateCopyResultCallback(&error, &results));
342 content::RunAllBlockingPoolTasksUntilIdle();
343 EXPECT_EQ(FILE_ERROR_OK, error);
344 ASSERT_EQ(1u, results.size());
345 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/File1"), results[0].path.value());
347 hashes.clear();
348 hashes.insert("md5#2");
349 file_system_->SearchByHashes(
350 hashes,
351 google_apis::test_util::CreateCopyResultCallback(&error, &results));
352 content::RunAllBlockingPoolTasksUntilIdle();
353 EXPECT_EQ(FILE_ERROR_OK, error);
354 ASSERT_EQ(2u, results.size());
355 std::sort(results.begin(), results.end(), &CompareHashAndFilePath);
356 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/File2"),
357 results[0].path.value());
358 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"),
359 results[1].path.value());
361 hashes.clear();
362 hashes.insert("md5#1");
363 hashes.insert("md5#2");
364 file_system_->SearchByHashes(
365 hashes,
366 google_apis::test_util::CreateCopyResultCallback(&error, &results));
367 content::RunAllBlockingPoolTasksUntilIdle();
368 EXPECT_EQ(FILE_ERROR_OK, error);
369 ASSERT_EQ(3u, results.size());
370 std::sort(results.begin(), results.end(), &CompareHashAndFilePath);
371 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/File1"), results[0].path.value());
372 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/File2"),
373 results[1].path.value());
374 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"),
375 results[2].path.value());
378 TEST_F(FileSystemTest, Copy) {
379 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
380 base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Copied.txt"));
381 EXPECT_TRUE(GetResourceEntrySync(src_file_path));
382 EXPECT_FALSE(GetResourceEntrySync(dest_file_path));
384 FileError error = FILE_ERROR_FAILED;
385 file_system_->Copy(src_file_path,
386 dest_file_path,
387 false, // preserve_last_modified,
388 google_apis::test_util::CreateCopyResultCallback(&error));
389 content::RunAllBlockingPoolTasksUntilIdle();
390 EXPECT_EQ(FILE_ERROR_OK, error);
392 // Entry is added on the server.
393 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(dest_file_path);
394 ASSERT_TRUE(entry);
396 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
397 scoped_ptr<google_apis::FileResource> server_entry;
398 fake_drive_service_->GetFileResource(
399 entry->resource_id(),
400 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
401 content::RunAllBlockingPoolTasksUntilIdle();
402 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
403 ASSERT_TRUE(server_entry);
404 EXPECT_EQ(entry->title(), server_entry->title());
405 EXPECT_FALSE(server_entry->IsDirectory());
408 TEST_F(FileSystemTest, Move) {
409 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
410 base::FilePath dest_file_path(
411 FILE_PATH_LITERAL("drive/root/Directory 1/Moved.txt"));
412 EXPECT_TRUE(GetResourceEntrySync(src_file_path));
413 EXPECT_FALSE(GetResourceEntrySync(dest_file_path));
414 scoped_ptr<ResourceEntry> parent =
415 GetResourceEntrySync(dest_file_path.DirName());
416 ASSERT_TRUE(parent);
418 FileError error = FILE_ERROR_FAILED;
419 file_system_->Move(src_file_path,
420 dest_file_path,
421 google_apis::test_util::CreateCopyResultCallback(&error));
422 content::RunAllBlockingPoolTasksUntilIdle();
423 EXPECT_EQ(FILE_ERROR_OK, error);
425 // Entry is moved on the server.
426 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(dest_file_path);
427 ASSERT_TRUE(entry);
429 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
430 scoped_ptr<google_apis::FileResource> server_entry;
431 fake_drive_service_->GetFileResource(
432 entry->resource_id(),
433 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
434 content::RunAllBlockingPoolTasksUntilIdle();
435 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
436 ASSERT_TRUE(server_entry);
437 EXPECT_EQ(entry->title(), server_entry->title());
439 ASSERT_FALSE(server_entry->parents().empty());
440 EXPECT_EQ(parent->resource_id(), server_entry->parents()[0].file_id());
443 TEST_F(FileSystemTest, Remove) {
444 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
445 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
446 ASSERT_TRUE(entry);
448 FileError error = FILE_ERROR_FAILED;
449 file_system_->Remove(
450 file_path,
451 false, // is_resursive
452 google_apis::test_util::CreateCopyResultCallback(&error));
453 content::RunAllBlockingPoolTasksUntilIdle();
454 EXPECT_EQ(FILE_ERROR_OK, error);
456 // Entry is removed on the server.
457 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
458 scoped_ptr<google_apis::FileResource> server_entry;
459 fake_drive_service_->GetFileResource(
460 entry->resource_id(),
461 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
462 content::RunAllBlockingPoolTasksUntilIdle();
463 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
464 ASSERT_TRUE(server_entry);
465 EXPECT_TRUE(server_entry->labels().is_trashed());
468 TEST_F(FileSystemTest, CreateDirectory) {
469 base::FilePath directory_path(FILE_PATH_LITERAL("drive/root/New Directory"));
470 EXPECT_FALSE(GetResourceEntrySync(directory_path));
472 FileError error = FILE_ERROR_FAILED;
473 file_system_->CreateDirectory(
474 directory_path,
475 true, // is_exclusive
476 false, // is_recursive
477 google_apis::test_util::CreateCopyResultCallback(&error));
478 content::RunAllBlockingPoolTasksUntilIdle();
479 EXPECT_EQ(FILE_ERROR_OK, error);
481 // Directory is created on the server.
482 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(directory_path);
483 ASSERT_TRUE(entry);
485 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
486 scoped_ptr<google_apis::FileResource> server_entry;
487 fake_drive_service_->GetFileResource(
488 entry->resource_id(),
489 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
490 content::RunAllBlockingPoolTasksUntilIdle();
491 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
492 ASSERT_TRUE(server_entry);
493 EXPECT_EQ(entry->title(), server_entry->title());
494 EXPECT_TRUE(server_entry->IsDirectory());
497 TEST_F(FileSystemTest, CreateFile) {
498 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/New File.txt"));
499 EXPECT_FALSE(GetResourceEntrySync(file_path));
501 FileError error = FILE_ERROR_FAILED;
502 file_system_->CreateFile(
503 file_path,
504 true, // is_exclusive
505 "text/plain",
506 google_apis::test_util::CreateCopyResultCallback(&error));
507 content::RunAllBlockingPoolTasksUntilIdle();
508 EXPECT_EQ(FILE_ERROR_OK, error);
510 // File is created on the server.
511 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
512 ASSERT_TRUE(entry);
514 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
515 scoped_ptr<google_apis::FileResource> server_entry;
516 fake_drive_service_->GetFileResource(
517 entry->resource_id(),
518 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
519 content::RunAllBlockingPoolTasksUntilIdle();
520 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
521 ASSERT_TRUE(server_entry);
522 EXPECT_EQ(entry->title(), server_entry->title());
523 EXPECT_FALSE(server_entry->IsDirectory());
526 TEST_F(FileSystemTest, TouchFile) {
527 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
528 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
529 ASSERT_TRUE(entry);
531 base::Time last_accessed =
532 base::Time::FromInternalValue(entry->file_info().last_accessed()) +
533 base::TimeDelta::FromSeconds(1);
534 base::Time last_modified =
535 base::Time::FromInternalValue(entry->file_info().last_modified()) +
536 base::TimeDelta::FromSeconds(1);
538 FileError error = FILE_ERROR_FAILED;
539 file_system_->TouchFile(
540 file_path,
541 last_accessed,
542 last_modified,
543 google_apis::test_util::CreateCopyResultCallback(&error));
544 content::RunAllBlockingPoolTasksUntilIdle();
545 EXPECT_EQ(FILE_ERROR_OK, error);
547 // File is touched on the server.
548 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
549 scoped_ptr<google_apis::FileResource> server_entry;
550 fake_drive_service_->GetFileResource(
551 entry->resource_id(),
552 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
553 content::RunAllBlockingPoolTasksUntilIdle();
554 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
555 ASSERT_TRUE(server_entry);
556 EXPECT_EQ(last_accessed, server_entry->last_viewed_by_me_date());
557 EXPECT_EQ(last_modified, server_entry->modified_date());
560 TEST_F(FileSystemTest, TruncateFile) {
561 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
562 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
563 ASSERT_TRUE(entry);
565 const int64 kLength = entry->file_info().size() + 100;
567 FileError error = FILE_ERROR_FAILED;
568 file_system_->TruncateFile(
569 file_path,
570 kLength,
571 google_apis::test_util::CreateCopyResultCallback(&error));
572 content::RunAllBlockingPoolTasksUntilIdle();
573 EXPECT_EQ(FILE_ERROR_OK, error);
575 // File is touched on the server.
576 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
577 scoped_ptr<google_apis::FileResource> server_entry;
578 fake_drive_service_->GetFileResource(
579 entry->resource_id(),
580 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
581 content::RunAllBlockingPoolTasksUntilIdle();
582 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
583 ASSERT_TRUE(server_entry);
584 EXPECT_EQ(kLength, server_entry->file_size());
587 TEST_F(FileSystemTest, DuplicatedAsyncInitialization) {
588 base::RunLoop loop;
590 int counter = 0;
591 const GetResourceEntryCallback& callback = base::Bind(
592 &AsyncInitializationCallback, &counter, 2, loop.QuitClosure());
594 file_system_->GetResourceEntry(
595 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback);
596 file_system_->GetResourceEntry(
597 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback);
598 loop.Run(); // Wait to get our result
599 EXPECT_EQ(2, counter);
601 EXPECT_EQ(1, fake_drive_service_->file_list_load_count());
604 TEST_F(FileSystemTest, GetGrandRootEntry) {
605 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive"));
606 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
607 ASSERT_TRUE(entry);
608 EXPECT_EQ(util::kDriveGrandRootLocalId, entry->local_id());
611 TEST_F(FileSystemTest, GetOtherDirEntry) {
612 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/other"));
613 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
614 ASSERT_TRUE(entry);
615 EXPECT_EQ(util::kDriveOtherDirLocalId, entry->local_id());
618 TEST_F(FileSystemTest, GetMyDriveRoot) {
619 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root"));
620 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
621 ASSERT_TRUE(entry);
622 EXPECT_EQ(fake_drive_service_->GetRootResourceId(), entry->resource_id());
624 // After "fast fetch" is done, full resource list is fetched.
625 EXPECT_EQ(1, fake_drive_service_->file_list_load_count());
628 TEST_F(FileSystemTest, GetExistingFile) {
629 // Simulate the situation that full feed fetching takes very long time,
630 // to test the recursive "fast fetch" feature is properly working.
631 fake_drive_service_->set_never_return_all_file_list(true);
633 const base::FilePath kFilePath(
634 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
635 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
636 ASSERT_TRUE(entry);
637 EXPECT_EQ("subdirectory_file_1_id", entry->resource_id());
639 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
640 EXPECT_EQ(2, fake_drive_service_->directory_load_count());
641 EXPECT_EQ(1, fake_drive_service_->blocked_file_list_load_count());
644 TEST_F(FileSystemTest, GetExistingDocument) {
645 const base::FilePath kFilePath(
646 FILE_PATH_LITERAL("drive/root/Document 1 excludeDir-test.gdoc"));
647 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
648 ASSERT_TRUE(entry);
649 EXPECT_EQ("5_document_resource_id", entry->resource_id());
652 TEST_F(FileSystemTest, GetNonExistingFile) {
653 const base::FilePath kFilePath(
654 FILE_PATH_LITERAL("drive/root/nonexisting.file"));
655 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
656 EXPECT_FALSE(entry);
659 TEST_F(FileSystemTest, GetInSubSubdir) {
660 const base::FilePath kFilePath(
661 FILE_PATH_LITERAL("drive/root/Directory 1/Sub Directory Folder/"
662 "Sub Sub Directory Folder"));
663 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
664 ASSERT_TRUE(entry);
665 ASSERT_EQ("sub_sub_directory_folder_id", entry->resource_id());
668 TEST_F(FileSystemTest, GetOrphanFile) {
669 ASSERT_TRUE(LoadFullResourceList());
671 // Entry without parents are placed under "drive/other".
672 const base::FilePath kFilePath(
673 FILE_PATH_LITERAL("drive/other/Orphan File 1.txt"));
674 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
675 ASSERT_TRUE(entry);
676 EXPECT_EQ("1_orphanfile_resource_id", entry->resource_id());
679 TEST_F(FileSystemTest, ReadDirectory_Root) {
680 // ReadDirectory() should kick off the resource list loading.
681 scoped_ptr<ResourceEntryVector> entries(
682 ReadDirectorySync(base::FilePath::FromUTF8Unsafe("drive")));
683 // The root directory should be read correctly.
684 ASSERT_TRUE(entries);
685 ASSERT_EQ(3U, entries->size());
687 // The found three directories should be /drive/root, /drive/other and
688 // /drive/trash.
689 std::set<base::FilePath> found;
690 for (size_t i = 0; i < entries->size(); ++i)
691 found.insert(base::FilePath::FromUTF8Unsafe((*entries)[i].title()));
692 EXPECT_EQ(3U, found.size());
693 EXPECT_EQ(1U, found.count(base::FilePath::FromUTF8Unsafe(
694 util::kDriveMyDriveRootDirName)));
695 EXPECT_EQ(1U, found.count(
696 base::FilePath::FromUTF8Unsafe(util::kDriveOtherDirName)));
697 EXPECT_EQ(1U, found.count(
698 base::FilePath::FromUTF8Unsafe(util::kDriveTrashDirName)));
701 TEST_F(FileSystemTest, ReadDirectory_NonRootDirectory) {
702 // ReadDirectory() should kick off the resource list loading.
703 scoped_ptr<ResourceEntryVector> entries(
704 ReadDirectorySync(
705 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
706 // The non root directory should also be read correctly.
707 // There was a bug (crbug.com/181487), which broke this behavior.
708 // Make sure this is fixed.
709 ASSERT_TRUE(entries);
710 EXPECT_EQ(3U, entries->size());
713 TEST_F(FileSystemTest, LoadFileSystemFromUpToDateCache) {
714 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP));
716 // Kicks loading of cached file system and query for server update.
717 EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
719 // SetUpTestFileSystem and FakeDriveService have the same
720 // changestamp (i.e. the local metadata is up-to-date), so no request for
721 // new resource list (i.e., call to GetResourceList) should happen.
722 EXPECT_EQ(0, fake_drive_service_->file_list_load_count());
724 // Since the file system has verified that it holds the latest snapshot,
725 // it should change its state to "loaded", which admits periodic refresh.
726 // To test it, call CheckForUpdates and verify it does try to check updates.
727 const int about_resource_load_count_before =
728 fake_drive_service_->about_resource_load_count();
729 file_system_->CheckForUpdates();
730 content::RunAllBlockingPoolTasksUntilIdle();
731 EXPECT_LT(about_resource_load_count_before,
732 fake_drive_service_->about_resource_load_count());
735 TEST_F(FileSystemTest, LoadFileSystemFromCacheWhileOffline) {
736 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
738 // Make GetResourceList fail for simulating offline situation. This will
739 // leave the file system "loaded from cache, but not synced with server"
740 // state.
741 fake_drive_service_->set_offline(true);
743 // Load the root.
744 EXPECT_TRUE(ReadDirectorySync(util::GetDriveGrandRootPath()));
745 // Loading of about resource should not happen as it's offline.
746 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
748 // Load "My Drive".
749 EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
750 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
752 // Tests that cached data can be loaded even if the server is not reachable.
753 EXPECT_TRUE(EntryExists(base::FilePath(
754 FILE_PATH_LITERAL("drive/root/File1"))));
755 EXPECT_TRUE(EntryExists(base::FilePath(
756 FILE_PATH_LITERAL("drive/root/Dir1"))));
757 EXPECT_TRUE(EntryExists(base::FilePath(
758 FILE_PATH_LITERAL("drive/root/Dir1/File2"))));
759 EXPECT_TRUE(EntryExists(base::FilePath(
760 FILE_PATH_LITERAL("drive/root/Dir1/SubDir2"))));
761 EXPECT_TRUE(EntryExists(base::FilePath(
762 FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"))));
764 // Since the file system has at least succeeded to load cached snapshot,
765 // the file system should be able to start periodic refresh.
766 // To test it, call CheckForUpdates and verify it does try to check
767 // updates, which will cause directory changes.
768 fake_drive_service_->set_offline(false);
770 file_system_->CheckForUpdates();
772 content::RunAllBlockingPoolTasksUntilIdle();
773 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
774 EXPECT_EQ(1, fake_drive_service_->change_list_load_count());
776 ASSERT_LE(0u, mock_directory_observer_->changed_directories().size());
777 ASSERT_LE(1u, mock_directory_observer_->changed_files().size());
780 TEST_F(FileSystemTest, ReadDirectoryWhileRefreshing) {
781 // Use old timestamp so the fast fetch will be performed.
782 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
784 // The list of resources in "drive/root/Dir1" should be fetched.
785 EXPECT_TRUE(ReadDirectorySync(base::FilePath(
786 FILE_PATH_LITERAL("drive/root/Dir1"))));
787 EXPECT_EQ(1, fake_drive_service_->directory_load_count());
789 ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
792 TEST_F(FileSystemTest, GetResourceEntryNonExistentWhileRefreshing) {
793 // Use old timestamp so the fast fetch will be performed.
794 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
796 // If an entry is not found, parent directory's resource list is fetched.
797 EXPECT_FALSE(GetResourceEntrySync(base::FilePath(
798 FILE_PATH_LITERAL("drive/root/Dir1/NonExistentFile"))));
799 EXPECT_EQ(1, fake_drive_service_->directory_load_count());
801 ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
804 TEST_F(FileSystemTest, CreateDirectoryByImplicitLoad) {
805 // Intentionally *not* calling LoadFullResourceList(), for testing that
806 // CreateDirectory ensures the resource list is loaded before it runs.
808 base::FilePath existing_directory(
809 FILE_PATH_LITERAL("drive/root/Directory 1"));
810 FileError error = FILE_ERROR_FAILED;
811 file_system_->CreateDirectory(
812 existing_directory,
813 true, // is_exclusive
814 false, // is_recursive
815 google_apis::test_util::CreateCopyResultCallback(&error));
816 content::RunAllBlockingPoolTasksUntilIdle();
818 // It should fail because is_exclusive is set to true.
819 EXPECT_EQ(FILE_ERROR_EXISTS, error);
822 TEST_F(FileSystemTest, CreateDirectoryRecursively) {
823 // Intentionally *not* calling LoadFullResourceList(), for testing that
824 // CreateDirectory ensures the resource list is loaded before it runs.
826 base::FilePath new_directory(
827 FILE_PATH_LITERAL("drive/root/Directory 1/a/b/c/d"));
828 FileError error = FILE_ERROR_FAILED;
829 file_system_->CreateDirectory(
830 new_directory,
831 true, // is_exclusive
832 true, // is_recursive
833 google_apis::test_util::CreateCopyResultCallback(&error));
834 content::RunAllBlockingPoolTasksUntilIdle();
836 EXPECT_EQ(FILE_ERROR_OK, error);
838 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(new_directory));
839 ASSERT_TRUE(entry);
840 EXPECT_TRUE(entry->file_info().is_directory());
843 TEST_F(FileSystemTest, ReadDirectoryAfterUpdateWhileLoading) {
844 // Simulate the situation that full feed fetching takes very long time,
845 // to test the recursive "fast fetch" feature is properly working.
846 fake_drive_service_->set_never_return_all_file_list(true);
848 // On the fake server, create the test directory.
849 scoped_ptr<google_apis::FileResource> parent;
851 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
852 fake_drive_service_->AddNewDirectory(
853 fake_drive_service_->GetRootResourceId(), "UpdateWhileLoadingTestDir",
854 AddNewDirectoryOptions(),
855 google_apis::test_util::CreateCopyResultCallback(&error, &parent));
856 base::RunLoop().RunUntilIdle();
857 ASSERT_EQ(google_apis::HTTP_CREATED, error);
860 // Fetch the directory. Currently it is empty.
861 scoped_ptr<ResourceEntryVector> before = ReadDirectorySync(base::FilePath(
862 FILE_PATH_LITERAL("drive/root/UpdateWhileLoadingTestDir")));
863 ASSERT_TRUE(before);
864 EXPECT_EQ(0u, before->size());
866 // Create a file in the test directory.
867 scoped_ptr<google_apis::FileResource> entry;
869 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
870 fake_drive_service_->AddNewFile(
871 "text/plain",
872 "(dummy data)",
873 parent->file_id(),
874 "TestFile",
875 false, // shared_with_me
876 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
877 base::RunLoop().RunUntilIdle();
878 ASSERT_EQ(google_apis::HTTP_CREATED, error);
881 // Notify the update to the file system.
882 file_system_->CheckForUpdates();
884 // Read the directory once again. Although the full feed fetching is not yet
885 // finished, the "fast fetch" of the directory works and the refreshed content
886 // is returned.
887 scoped_ptr<ResourceEntryVector> after = ReadDirectorySync(base::FilePath(
888 FILE_PATH_LITERAL("drive/root/UpdateWhileLoadingTestDir")));
889 ASSERT_TRUE(after);
890 EXPECT_EQ(1u, after->size());
893 TEST_F(FileSystemTest, PinAndUnpin) {
894 ASSERT_TRUE(LoadFullResourceList());
896 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
898 // Get the file info.
899 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
900 ASSERT_TRUE(entry);
902 // Pin the file.
903 FileError error = FILE_ERROR_FAILED;
904 file_system_->Pin(file_path,
905 google_apis::test_util::CreateCopyResultCallback(&error));
906 content::RunAllBlockingPoolTasksUntilIdle();
907 EXPECT_EQ(FILE_ERROR_OK, error);
909 entry = GetResourceEntrySync(file_path);
910 ASSERT_TRUE(entry);
911 EXPECT_TRUE(entry->file_specific_info().cache_state().is_pinned());
912 EXPECT_TRUE(entry->file_specific_info().cache_state().is_present());
914 // Unpin the file.
915 error = FILE_ERROR_FAILED;
916 file_system_->Unpin(file_path,
917 google_apis::test_util::CreateCopyResultCallback(&error));
918 content::RunAllBlockingPoolTasksUntilIdle();
919 EXPECT_EQ(FILE_ERROR_OK, error);
921 entry = GetResourceEntrySync(file_path);
922 ASSERT_TRUE(entry);
923 EXPECT_FALSE(entry->file_specific_info().cache_state().is_pinned());
925 // Pinned file gets synced and it results in entry state changes.
926 ASSERT_EQ(0u, mock_directory_observer_->changed_directories().size());
927 ASSERT_EQ(1u, mock_directory_observer_->changed_files().size());
928 EXPECT_EQ(1u,
929 mock_directory_observer_->changed_files().CountDirectory(
930 base::FilePath(FILE_PATH_LITERAL("drive/root"))));
933 TEST_F(FileSystemTest, PinAndUnpin_NotSynced) {
934 ASSERT_TRUE(LoadFullResourceList());
936 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
938 // Get the file info.
939 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
940 ASSERT_TRUE(entry);
942 // Unpin the file just after pinning. File fetch should be cancelled.
943 FileError error_pin = FILE_ERROR_FAILED;
944 file_system_->Pin(
945 file_path,
946 google_apis::test_util::CreateCopyResultCallback(&error_pin));
948 FileError error_unpin = FILE_ERROR_FAILED;
949 file_system_->Unpin(
950 file_path,
951 google_apis::test_util::CreateCopyResultCallback(&error_unpin));
953 content::RunAllBlockingPoolTasksUntilIdle();
954 EXPECT_EQ(FILE_ERROR_OK, error_pin);
955 EXPECT_EQ(FILE_ERROR_OK, error_unpin);
957 // No cache file available because the sync was cancelled by Unpin().
958 entry = GetResourceEntrySync(file_path);
959 ASSERT_TRUE(entry);
960 EXPECT_FALSE(entry->file_specific_info().cache_state().is_present());
963 TEST_F(FileSystemTest, GetAvailableSpace) {
964 FileError error = FILE_ERROR_OK;
965 int64 bytes_total;
966 int64 bytes_used;
967 file_system_->GetAvailableSpace(
968 google_apis::test_util::CreateCopyResultCallback(
969 &error, &bytes_total, &bytes_used));
970 content::RunAllBlockingPoolTasksUntilIdle();
971 EXPECT_EQ(6789012345LL, bytes_used);
972 EXPECT_EQ(9876543210LL, bytes_total);
975 TEST_F(FileSystemTest, MarkCacheFileAsMountedAndUnmounted) {
976 ASSERT_TRUE(LoadFullResourceList());
978 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
980 // Make the file cached.
981 FileError error = FILE_ERROR_FAILED;
982 base::FilePath file_path;
983 scoped_ptr<ResourceEntry> entry;
984 file_system_->GetFile(
985 file_in_root,
986 google_apis::test_util::CreateCopyResultCallback(
987 &error, &file_path, &entry));
988 content::RunAllBlockingPoolTasksUntilIdle();
989 EXPECT_EQ(FILE_ERROR_OK, error);
991 // Test for mounting.
992 error = FILE_ERROR_FAILED;
993 file_path.clear();
994 file_system_->MarkCacheFileAsMounted(
995 file_in_root,
996 google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
997 content::RunAllBlockingPoolTasksUntilIdle();
998 EXPECT_EQ(FILE_ERROR_OK, error);
1000 // Cannot remove a cache entry while it's being mounted.
1001 EXPECT_EQ(FILE_ERROR_IN_USE, cache_->Remove(entry->local_id()));
1003 // Test for unmounting.
1004 error = FILE_ERROR_FAILED;
1005 file_system_->MarkCacheFileAsUnmounted(
1006 file_path,
1007 google_apis::test_util::CreateCopyResultCallback(&error));
1008 content::RunAllBlockingPoolTasksUntilIdle();
1009 EXPECT_EQ(FILE_ERROR_OK, error);
1011 // Now able to remove the cache entry.
1012 EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(entry->local_id()));
1015 TEST_F(FileSystemTest, GetShareUrl) {
1016 ASSERT_TRUE(LoadFullResourceList());
1018 const base::FilePath kFileInRoot(FILE_PATH_LITERAL("drive/root/File 1.txt"));
1019 const GURL kEmbedOrigin("chrome-extension://test-id");
1021 // Try to fetch the URL for the sharing dialog.
1022 FileError error = FILE_ERROR_FAILED;
1023 GURL share_url;
1024 file_system_->GetShareUrl(
1025 kFileInRoot,
1026 kEmbedOrigin,
1027 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
1028 content::RunAllBlockingPoolTasksUntilIdle();
1030 // Verify the share url to the sharing dialog.
1031 EXPECT_EQ(FILE_ERROR_OK, error);
1032 EXPECT_TRUE(share_url.is_valid());
1035 TEST_F(FileSystemTest, FreeDiskSpaceIfNeededFor) {
1036 ASSERT_TRUE(LoadFullResourceList());
1038 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
1040 // Make the file cached.
1041 FileError error = FILE_ERROR_FAILED;
1042 base::FilePath file_path;
1043 scoped_ptr<ResourceEntry> entry;
1044 file_system_->GetFile(file_in_root,
1045 google_apis::test_util::CreateCopyResultCallback(
1046 &error, &file_path, &entry));
1047 content::RunAllBlockingPoolTasksUntilIdle();
1048 EXPECT_EQ(FILE_ERROR_OK, error);
1049 ASSERT_TRUE(entry);
1050 EXPECT_TRUE(entry->file_specific_info().cache_state().is_present());
1052 bool available;
1053 file_system_->FreeDiskSpaceIfNeededFor(
1054 512LL << 40,
1055 google_apis::test_util::CreateCopyResultCallback(&available));
1056 content::RunAllBlockingPoolTasksUntilIdle();
1057 ASSERT_FALSE(available);
1059 entry = GetResourceEntrySync(file_in_root);
1060 ASSERT_TRUE(entry);
1061 EXPECT_FALSE(entry->file_specific_info().cache_state().is_present());
1064 } // namespace drive