Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / file_system_unittest.cc
blob2c22a657d950773d3a60898aad24d424f5b33ed6
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"
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/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_change.h"
22 #include "chrome/browser/chromeos/drive/file_system_observer.h"
23 #include "chrome/browser/chromeos/drive/file_system_util.h"
24 #include "chrome/browser/chromeos/drive/job_scheduler.h"
25 #include "chrome/browser/chromeos/drive/sync_client.h"
26 #include "chrome/browser/chromeos/drive/test_util.h"
27 #include "chrome/browser/drive/drive_api_util.h"
28 #include "chrome/browser/drive/event_logger.h"
29 #include "chrome/browser/drive/fake_drive_service.h"
30 #include "chrome/browser/drive/test_util.h"
31 #include "content/public/test/test_browser_thread_bundle.h"
32 #include "google_apis/drive/drive_api_parser.h"
33 #include "google_apis/drive/test_util.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 namespace drive {
37 namespace {
39 // Counts the number of invocation, and if it increased up to |expected_counter|
40 // quits the current message loop by calling |quit|.
41 void AsyncInitializationCallback(
42 int* counter, int expected_counter, const base::Closure& quit,
43 FileError error, scoped_ptr<ResourceEntry> entry) {
44 if (error != FILE_ERROR_OK || !entry) {
45 // If we hit an error case, quit the message loop immediately.
46 // Then the expectation in the test case can find it because the actual
47 // value of |counter| is different from the expected one.
48 quit.Run();
49 return;
52 (*counter)++;
53 if (*counter >= expected_counter)
54 quit.Run();
57 bool CompareHashAndFilePath(const HashAndFilePath& a,
58 const HashAndFilePath& b) {
59 const int result = a.hash.compare(b.hash);
60 if (result < 0)
61 return true;
62 if (result > 0)
63 return false;
64 return a.path.AsUTF8Unsafe().compare(b.path.AsUTF8Unsafe()) < 0;
67 // This class is used to record directory changes and examine them later.
68 class MockDirectoryChangeObserver : public FileSystemObserver {
69 public:
70 MockDirectoryChangeObserver() {}
71 ~MockDirectoryChangeObserver() override {}
73 // FileSystemObserver overrides.
74 void OnDirectoryChanged(const base::FilePath& directory_path) override {
75 changed_directories_.push_back(directory_path);
78 void OnFileChanged(const FileChange& new_file_change) override {
79 changed_files_.Apply(new_file_change);
82 const std::vector<base::FilePath>& changed_directories() const {
83 return changed_directories_;
86 const FileChange& changed_files() const { return changed_files_; }
88 private:
89 std::vector<base::FilePath> changed_directories_;
90 FileChange changed_files_;
91 DISALLOW_COPY_AND_ASSIGN(MockDirectoryChangeObserver);
94 } // namespace
96 class FileSystemTest : public testing::Test {
97 protected:
98 void SetUp() override {
99 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
100 pref_service_.reset(new TestingPrefServiceSimple);
101 test_util::RegisterDrivePrefs(pref_service_->registry());
103 logger_.reset(new EventLogger);
104 fake_drive_service_.reset(new FakeDriveService);
105 test_util::SetUpTestEntries(fake_drive_service_.get());
107 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
109 scheduler_.reset(new JobScheduler(pref_service_.get(),
110 logger_.get(),
111 fake_drive_service_.get(),
112 base::MessageLoopProxy::current().get()));
114 mock_directory_observer_.reset(new MockDirectoryChangeObserver);
116 SetUpResourceMetadataAndFileSystem();
119 void SetUpResourceMetadataAndFileSystem() {
120 const base::FilePath metadata_dir = temp_dir_.path().AppendASCII("meta");
121 ASSERT_TRUE(base::CreateDirectory(metadata_dir));
122 metadata_storage_.reset(new internal::ResourceMetadataStorage(
123 metadata_dir, base::MessageLoopProxy::current().get()));
124 ASSERT_TRUE(metadata_storage_->Initialize());
126 const base::FilePath cache_dir = temp_dir_.path().AppendASCII("files");
127 ASSERT_TRUE(base::CreateDirectory(cache_dir));
128 cache_.reset(new internal::FileCache(
129 metadata_storage_.get(),
130 cache_dir,
131 base::MessageLoopProxy::current().get(),
132 fake_free_disk_space_getter_.get()));
133 ASSERT_TRUE(cache_->Initialize());
135 resource_metadata_.reset(new internal::ResourceMetadata(
136 metadata_storage_.get(), cache_.get(),
137 base::MessageLoopProxy::current()));
138 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
140 const base::FilePath temp_file_dir = temp_dir_.path().AppendASCII("tmp");
141 ASSERT_TRUE(base::CreateDirectory(temp_file_dir));
142 file_system_.reset(new FileSystem(
143 pref_service_.get(),
144 logger_.get(),
145 cache_.get(),
146 scheduler_.get(),
147 resource_metadata_.get(),
148 base::MessageLoopProxy::current().get(),
149 temp_file_dir));
150 file_system_->AddObserver(mock_directory_observer_.get());
152 // Disable delaying so that the sync starts immediately.
153 file_system_->sync_client_for_testing()->set_delay_for_testing(
154 base::TimeDelta::FromSeconds(0));
157 // Loads the full resource list via FakeDriveService.
158 bool LoadFullResourceList() {
159 FileError error = FILE_ERROR_FAILED;
160 file_system_->change_list_loader_for_testing()->LoadIfNeeded(
161 google_apis::test_util::CreateCopyResultCallback(&error));
162 content::RunAllBlockingPoolTasksUntilIdle();
163 return error == FILE_ERROR_OK;
166 // Gets resource entry by path synchronously.
167 scoped_ptr<ResourceEntry> GetResourceEntrySync(
168 const base::FilePath& file_path) {
169 FileError error = FILE_ERROR_FAILED;
170 scoped_ptr<ResourceEntry> entry;
171 file_system_->GetResourceEntry(
172 file_path,
173 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
174 content::RunAllBlockingPoolTasksUntilIdle();
176 return entry.Pass();
179 // Gets directory info by path synchronously.
180 scoped_ptr<ResourceEntryVector> ReadDirectorySync(
181 const base::FilePath& file_path) {
182 FileError error = FILE_ERROR_FAILED;
183 scoped_ptr<ResourceEntryVector> entries(new ResourceEntryVector);
184 file_system_->ReadDirectory(
185 file_path,
186 base::Bind(&AccumulateReadDirectoryResult, entries.get()),
187 google_apis::test_util::CreateCopyResultCallback(&error));
188 content::RunAllBlockingPoolTasksUntilIdle();
189 if (error != FILE_ERROR_OK)
190 entries.reset();
191 return entries.Pass();
194 // Used to implement ReadDirectorySync().
195 static void AccumulateReadDirectoryResult(
196 ResourceEntryVector* out_entries,
197 scoped_ptr<ResourceEntryVector> entries) {
198 ASSERT_TRUE(entries);
199 out_entries->insert(out_entries->end(), entries->begin(), entries->end());
202 // Returns true if an entry exists at |file_path|.
203 bool EntryExists(const base::FilePath& file_path) {
204 return GetResourceEntrySync(file_path);
207 // Flag for specifying the timestamp of the test filesystem cache.
208 enum SetUpTestFileSystemParam {
209 USE_OLD_TIMESTAMP,
210 USE_SERVER_TIMESTAMP,
213 // Sets up a filesystem with directories: drive/root, drive/root/Dir1,
214 // drive/root/Dir1/SubDir2 and files drive/root/File1, drive/root/Dir1/File2,
215 // drive/root/Dir1/SubDir2/File3. If |use_up_to_date_timestamp| is true, sets
216 // the changestamp to that of FakeDriveService, indicating the cache is
217 // holding the latest file system info.
218 void SetUpTestFileSystem(SetUpTestFileSystemParam param) {
219 // Destroy the existing resource metadata to close DB.
220 resource_metadata_.reset();
222 const base::FilePath metadata_dir = temp_dir_.path().AppendASCII("meta");
223 ASSERT_TRUE(base::CreateDirectory(metadata_dir));
224 scoped_ptr<internal::ResourceMetadataStorage,
225 test_util::DestroyHelperForTests> metadata_storage(
226 new internal::ResourceMetadataStorage(
227 metadata_dir, base::MessageLoopProxy::current().get()));
229 const base::FilePath cache_dir = temp_dir_.path().AppendASCII("files");
230 scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache(
231 new internal::FileCache(metadata_storage.get(),
232 cache_dir,
233 base::MessageLoopProxy::current().get(),
234 fake_free_disk_space_getter_.get()));
236 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
237 resource_metadata(new internal::ResourceMetadata(
238 metadata_storage_.get(), cache.get(),
239 base::MessageLoopProxy::current()));
241 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->Initialize());
243 const int64 changestamp = param == USE_SERVER_TIMESTAMP ?
244 fake_drive_service_->about_resource().largest_change_id() : 1;
245 ASSERT_EQ(FILE_ERROR_OK,
246 resource_metadata->SetLargestChangestamp(changestamp));
248 // drive/root
249 ResourceEntry root;
250 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->GetResourceEntryByPath(
251 util::GetDriveMyDriveRootPath(), &root));
252 root.set_resource_id(fake_drive_service_->GetRootResourceId());
253 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->RefreshEntry(root));
255 std::string local_id;
257 // drive/root/File1
258 ResourceEntry file1;
259 file1.set_title("File1");
260 file1.set_resource_id("resource_id:File1");
261 file1.set_parent_local_id(root.local_id());
262 file1.mutable_file_specific_info()->set_md5("md5#1");
263 file1.mutable_file_info()->set_is_directory(false);
264 file1.mutable_file_info()->set_size(1048576);
265 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file1, &local_id));
267 // drive/root/Dir1
268 ResourceEntry dir1;
269 dir1.set_title("Dir1");
270 dir1.set_resource_id("resource_id:Dir1");
271 dir1.set_parent_local_id(root.local_id());
272 dir1.mutable_file_info()->set_is_directory(true);
273 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(dir1, &local_id));
274 const std::string dir1_local_id = local_id;
276 // drive/root/Dir1/File2
277 ResourceEntry file2;
278 file2.set_title("File2");
279 file2.set_resource_id("resource_id:File2");
280 file2.set_parent_local_id(dir1_local_id);
281 file2.mutable_file_specific_info()->set_md5("md5#2");
282 file2.mutable_file_info()->set_is_directory(false);
283 file2.mutable_file_info()->set_size(555);
284 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file2, &local_id));
286 // drive/root/Dir1/SubDir2
287 ResourceEntry dir2;
288 dir2.set_title("SubDir2");
289 dir2.set_resource_id("resource_id:SubDir2");
290 dir2.set_parent_local_id(dir1_local_id);
291 dir2.mutable_file_info()->set_is_directory(true);
292 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(dir2, &local_id));
293 const std::string dir2_local_id = local_id;
295 // drive/root/Dir1/SubDir2/File3
296 ResourceEntry file3;
297 file3.set_title("File3");
298 file3.set_resource_id("resource_id:File3");
299 file3.set_parent_local_id(dir2_local_id);
300 file3.mutable_file_specific_info()->set_md5("md5#2");
301 file3.mutable_file_info()->set_is_directory(false);
302 file3.mutable_file_info()->set_size(12345);
303 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file3, &local_id));
305 // Recreate resource metadata.
306 SetUpResourceMetadataAndFileSystem();
309 content::TestBrowserThreadBundle thread_bundle_;
310 base::ScopedTempDir temp_dir_;
311 // We don't use TestingProfile::GetPrefs() in favor of having less
312 // dependencies to Profile in general.
313 scoped_ptr<TestingPrefServiceSimple> pref_service_;
315 scoped_ptr<EventLogger> logger_;
316 scoped_ptr<FakeDriveService> fake_drive_service_;
317 scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
318 scoped_ptr<JobScheduler> scheduler_;
319 scoped_ptr<MockDirectoryChangeObserver> mock_directory_observer_;
321 scoped_ptr<internal::ResourceMetadataStorage,
322 test_util::DestroyHelperForTests> metadata_storage_;
323 scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache_;
324 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
325 resource_metadata_;
326 scoped_ptr<FileSystem> file_system_;
329 TEST_F(FileSystemTest, SearchByHashes) {
330 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP));
332 std::set<std::string> hashes;
333 FileError error;
334 std::vector<HashAndFilePath> results;
336 hashes.insert("md5#1");
337 file_system_->SearchByHashes(
338 hashes,
339 google_apis::test_util::CreateCopyResultCallback(&error, &results));
340 content::RunAllBlockingPoolTasksUntilIdle();
341 EXPECT_EQ(FILE_ERROR_OK, error);
342 ASSERT_EQ(1u, results.size());
343 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/File1"), results[0].path.value());
345 hashes.clear();
346 hashes.insert("md5#2");
347 file_system_->SearchByHashes(
348 hashes,
349 google_apis::test_util::CreateCopyResultCallback(&error, &results));
350 content::RunAllBlockingPoolTasksUntilIdle();
351 EXPECT_EQ(FILE_ERROR_OK, error);
352 ASSERT_EQ(2u, results.size());
353 std::sort(results.begin(), results.end(), &CompareHashAndFilePath);
354 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/File2"),
355 results[0].path.value());
356 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"),
357 results[1].path.value());
359 hashes.clear();
360 hashes.insert("md5#1");
361 hashes.insert("md5#2");
362 file_system_->SearchByHashes(
363 hashes,
364 google_apis::test_util::CreateCopyResultCallback(&error, &results));
365 content::RunAllBlockingPoolTasksUntilIdle();
366 EXPECT_EQ(FILE_ERROR_OK, error);
367 ASSERT_EQ(3u, results.size());
368 std::sort(results.begin(), results.end(), &CompareHashAndFilePath);
369 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/File1"), results[0].path.value());
370 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/File2"),
371 results[1].path.value());
372 EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"),
373 results[2].path.value());
376 TEST_F(FileSystemTest, Copy) {
377 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
378 base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Copied.txt"));
379 EXPECT_TRUE(GetResourceEntrySync(src_file_path));
380 EXPECT_FALSE(GetResourceEntrySync(dest_file_path));
382 FileError error = FILE_ERROR_FAILED;
383 file_system_->Copy(src_file_path,
384 dest_file_path,
385 false, // preserve_last_modified,
386 google_apis::test_util::CreateCopyResultCallback(&error));
387 content::RunAllBlockingPoolTasksUntilIdle();
388 EXPECT_EQ(FILE_ERROR_OK, error);
390 // Entry is added on the server.
391 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(dest_file_path);
392 ASSERT_TRUE(entry);
394 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
395 scoped_ptr<google_apis::FileResource> server_entry;
396 fake_drive_service_->GetFileResource(
397 entry->resource_id(),
398 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
399 content::RunAllBlockingPoolTasksUntilIdle();
400 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
401 ASSERT_TRUE(server_entry);
402 EXPECT_EQ(entry->title(), server_entry->title());
403 EXPECT_FALSE(server_entry->IsDirectory());
406 TEST_F(FileSystemTest, Move) {
407 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
408 base::FilePath dest_file_path(
409 FILE_PATH_LITERAL("drive/root/Directory 1/Moved.txt"));
410 EXPECT_TRUE(GetResourceEntrySync(src_file_path));
411 EXPECT_FALSE(GetResourceEntrySync(dest_file_path));
412 scoped_ptr<ResourceEntry> parent =
413 GetResourceEntrySync(dest_file_path.DirName());
414 ASSERT_TRUE(parent);
416 FileError error = FILE_ERROR_FAILED;
417 file_system_->Move(src_file_path,
418 dest_file_path,
419 google_apis::test_util::CreateCopyResultCallback(&error));
420 content::RunAllBlockingPoolTasksUntilIdle();
421 EXPECT_EQ(FILE_ERROR_OK, error);
423 // Entry is moved on the server.
424 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(dest_file_path);
425 ASSERT_TRUE(entry);
427 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
428 scoped_ptr<google_apis::FileResource> server_entry;
429 fake_drive_service_->GetFileResource(
430 entry->resource_id(),
431 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
432 content::RunAllBlockingPoolTasksUntilIdle();
433 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
434 ASSERT_TRUE(server_entry);
435 EXPECT_EQ(entry->title(), server_entry->title());
437 ASSERT_FALSE(server_entry->parents().empty());
438 EXPECT_EQ(parent->resource_id(), server_entry->parents()[0].file_id());
441 TEST_F(FileSystemTest, Remove) {
442 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
443 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
444 ASSERT_TRUE(entry);
446 FileError error = FILE_ERROR_FAILED;
447 file_system_->Remove(
448 file_path,
449 false, // is_resursive
450 google_apis::test_util::CreateCopyResultCallback(&error));
451 content::RunAllBlockingPoolTasksUntilIdle();
452 EXPECT_EQ(FILE_ERROR_OK, error);
454 // Entry is removed on the server.
455 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
456 scoped_ptr<google_apis::FileResource> server_entry;
457 fake_drive_service_->GetFileResource(
458 entry->resource_id(),
459 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
460 content::RunAllBlockingPoolTasksUntilIdle();
461 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
462 ASSERT_TRUE(server_entry);
463 EXPECT_TRUE(server_entry->labels().is_trashed());
466 TEST_F(FileSystemTest, CreateDirectory) {
467 base::FilePath directory_path(FILE_PATH_LITERAL("drive/root/New Directory"));
468 EXPECT_FALSE(GetResourceEntrySync(directory_path));
470 FileError error = FILE_ERROR_FAILED;
471 file_system_->CreateDirectory(
472 directory_path,
473 true, // is_exclusive
474 false, // is_recursive
475 google_apis::test_util::CreateCopyResultCallback(&error));
476 content::RunAllBlockingPoolTasksUntilIdle();
477 EXPECT_EQ(FILE_ERROR_OK, error);
479 // Directory is created on the server.
480 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(directory_path);
481 ASSERT_TRUE(entry);
483 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
484 scoped_ptr<google_apis::FileResource> server_entry;
485 fake_drive_service_->GetFileResource(
486 entry->resource_id(),
487 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
488 content::RunAllBlockingPoolTasksUntilIdle();
489 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
490 ASSERT_TRUE(server_entry);
491 EXPECT_EQ(entry->title(), server_entry->title());
492 EXPECT_TRUE(server_entry->IsDirectory());
495 TEST_F(FileSystemTest, CreateFile) {
496 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/New File.txt"));
497 EXPECT_FALSE(GetResourceEntrySync(file_path));
499 FileError error = FILE_ERROR_FAILED;
500 file_system_->CreateFile(
501 file_path,
502 true, // is_exclusive
503 "text/plain",
504 google_apis::test_util::CreateCopyResultCallback(&error));
505 content::RunAllBlockingPoolTasksUntilIdle();
506 EXPECT_EQ(FILE_ERROR_OK, error);
508 // File is created on the server.
509 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
510 ASSERT_TRUE(entry);
512 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
513 scoped_ptr<google_apis::FileResource> server_entry;
514 fake_drive_service_->GetFileResource(
515 entry->resource_id(),
516 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
517 content::RunAllBlockingPoolTasksUntilIdle();
518 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
519 ASSERT_TRUE(server_entry);
520 EXPECT_EQ(entry->title(), server_entry->title());
521 EXPECT_FALSE(server_entry->IsDirectory());
524 TEST_F(FileSystemTest, TouchFile) {
525 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
526 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
527 ASSERT_TRUE(entry);
529 base::Time last_accessed =
530 base::Time::FromInternalValue(entry->file_info().last_accessed()) +
531 base::TimeDelta::FromSeconds(1);
532 base::Time last_modified =
533 base::Time::FromInternalValue(entry->file_info().last_modified()) +
534 base::TimeDelta::FromSeconds(1);
536 FileError error = FILE_ERROR_FAILED;
537 file_system_->TouchFile(
538 file_path,
539 last_accessed,
540 last_modified,
541 google_apis::test_util::CreateCopyResultCallback(&error));
542 content::RunAllBlockingPoolTasksUntilIdle();
543 EXPECT_EQ(FILE_ERROR_OK, error);
545 // File is touched on the server.
546 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
547 scoped_ptr<google_apis::FileResource> server_entry;
548 fake_drive_service_->GetFileResource(
549 entry->resource_id(),
550 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
551 content::RunAllBlockingPoolTasksUntilIdle();
552 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
553 ASSERT_TRUE(server_entry);
554 EXPECT_EQ(last_accessed, server_entry->last_viewed_by_me_date());
555 EXPECT_EQ(last_modified, server_entry->modified_date());
558 TEST_F(FileSystemTest, TruncateFile) {
559 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
560 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(file_path);
561 ASSERT_TRUE(entry);
563 const int64 kLength = entry->file_info().size() + 100;
565 FileError error = FILE_ERROR_FAILED;
566 file_system_->TruncateFile(
567 file_path,
568 kLength,
569 google_apis::test_util::CreateCopyResultCallback(&error));
570 content::RunAllBlockingPoolTasksUntilIdle();
571 EXPECT_EQ(FILE_ERROR_OK, error);
573 // File is touched on the server.
574 google_apis::DriveApiErrorCode status = google_apis::DRIVE_OTHER_ERROR;
575 scoped_ptr<google_apis::FileResource> server_entry;
576 fake_drive_service_->GetFileResource(
577 entry->resource_id(),
578 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
579 content::RunAllBlockingPoolTasksUntilIdle();
580 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
581 ASSERT_TRUE(server_entry);
582 EXPECT_EQ(kLength, server_entry->file_size());
585 TEST_F(FileSystemTest, DuplicatedAsyncInitialization) {
586 base::RunLoop loop;
588 int counter = 0;
589 const GetResourceEntryCallback& callback = base::Bind(
590 &AsyncInitializationCallback, &counter, 2, loop.QuitClosure());
592 file_system_->GetResourceEntry(
593 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback);
594 file_system_->GetResourceEntry(
595 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback);
596 loop.Run(); // Wait to get our result
597 EXPECT_EQ(2, counter);
599 EXPECT_EQ(1, fake_drive_service_->file_list_load_count());
602 TEST_F(FileSystemTest, GetGrandRootEntry) {
603 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive"));
604 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
605 ASSERT_TRUE(entry);
606 EXPECT_EQ(util::kDriveGrandRootLocalId, entry->local_id());
609 TEST_F(FileSystemTest, GetOtherDirEntry) {
610 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/other"));
611 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
612 ASSERT_TRUE(entry);
613 EXPECT_EQ(util::kDriveOtherDirLocalId, entry->local_id());
616 TEST_F(FileSystemTest, GetMyDriveRoot) {
617 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root"));
618 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
619 ASSERT_TRUE(entry);
620 EXPECT_EQ(fake_drive_service_->GetRootResourceId(), entry->resource_id());
622 // After "fast fetch" is done, full resource list is fetched.
623 EXPECT_EQ(1, fake_drive_service_->file_list_load_count());
626 TEST_F(FileSystemTest, GetExistingFile) {
627 // Simulate the situation that full feed fetching takes very long time,
628 // to test the recursive "fast fetch" feature is properly working.
629 fake_drive_service_->set_never_return_all_file_list(true);
631 const base::FilePath kFilePath(
632 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
633 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
634 ASSERT_TRUE(entry);
635 EXPECT_EQ("subdirectory_file_1_id", entry->resource_id());
637 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
638 EXPECT_EQ(2, fake_drive_service_->directory_load_count());
639 EXPECT_EQ(1, fake_drive_service_->blocked_file_list_load_count());
642 TEST_F(FileSystemTest, GetExistingDocument) {
643 const base::FilePath kFilePath(
644 FILE_PATH_LITERAL("drive/root/Document 1 excludeDir-test.gdoc"));
645 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
646 ASSERT_TRUE(entry);
647 EXPECT_EQ("5_document_resource_id", entry->resource_id());
650 TEST_F(FileSystemTest, GetNonExistingFile) {
651 const base::FilePath kFilePath(
652 FILE_PATH_LITERAL("drive/root/nonexisting.file"));
653 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
654 EXPECT_FALSE(entry);
657 TEST_F(FileSystemTest, GetInSubSubdir) {
658 const base::FilePath kFilePath(
659 FILE_PATH_LITERAL("drive/root/Directory 1/Sub Directory Folder/"
660 "Sub Sub Directory Folder"));
661 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
662 ASSERT_TRUE(entry);
663 ASSERT_EQ("sub_sub_directory_folder_id", entry->resource_id());
666 TEST_F(FileSystemTest, GetOrphanFile) {
667 ASSERT_TRUE(LoadFullResourceList());
669 // Entry without parents are placed under "drive/other".
670 const base::FilePath kFilePath(
671 FILE_PATH_LITERAL("drive/other/Orphan File 1.txt"));
672 scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
673 ASSERT_TRUE(entry);
674 EXPECT_EQ("1_orphanfile_resource_id", entry->resource_id());
677 TEST_F(FileSystemTest, ReadDirectory_Root) {
678 // ReadDirectory() should kick off the resource list loading.
679 scoped_ptr<ResourceEntryVector> entries(
680 ReadDirectorySync(base::FilePath::FromUTF8Unsafe("drive")));
681 // The root directory should be read correctly.
682 ASSERT_TRUE(entries);
683 ASSERT_EQ(3U, entries->size());
685 // The found three directories should be /drive/root, /drive/other and
686 // /drive/trash.
687 std::set<base::FilePath> found;
688 for (size_t i = 0; i < entries->size(); ++i)
689 found.insert(base::FilePath::FromUTF8Unsafe((*entries)[i].title()));
690 EXPECT_EQ(3U, found.size());
691 EXPECT_EQ(1U, found.count(base::FilePath(util::kDriveMyDriveRootDirName)));
692 EXPECT_EQ(1U, found.count(base::FilePath(util::kDriveOtherDirName)));
693 EXPECT_EQ(1U, found.count(base::FilePath(util::kDriveTrashDirName)));
696 TEST_F(FileSystemTest, ReadDirectory_NonRootDirectory) {
697 // ReadDirectory() should kick off the resource list loading.
698 scoped_ptr<ResourceEntryVector> entries(
699 ReadDirectorySync(
700 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
701 // The non root directory should also be read correctly.
702 // There was a bug (crbug.com/181487), which broke this behavior.
703 // Make sure this is fixed.
704 ASSERT_TRUE(entries);
705 EXPECT_EQ(3U, entries->size());
708 TEST_F(FileSystemTest, LoadFileSystemFromUpToDateCache) {
709 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP));
711 // Kicks loading of cached file system and query for server update.
712 EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
714 // SetUpTestFileSystem and FakeDriveService have the same
715 // changestamp (i.e. the local metadata is up-to-date), so no request for
716 // new resource list (i.e., call to GetResourceList) should happen.
717 EXPECT_EQ(0, fake_drive_service_->file_list_load_count());
719 // Since the file system has verified that it holds the latest snapshot,
720 // it should change its state to "loaded", which admits periodic refresh.
721 // To test it, call CheckForUpdates and verify it does try to check updates.
722 const int about_resource_load_count_before =
723 fake_drive_service_->about_resource_load_count();
724 file_system_->CheckForUpdates();
725 content::RunAllBlockingPoolTasksUntilIdle();
726 EXPECT_LT(about_resource_load_count_before,
727 fake_drive_service_->about_resource_load_count());
730 TEST_F(FileSystemTest, LoadFileSystemFromCacheWhileOffline) {
731 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
733 // Make GetResourceList fail for simulating offline situation. This will
734 // leave the file system "loaded from cache, but not synced with server"
735 // state.
736 fake_drive_service_->set_offline(true);
738 // Load the root.
739 EXPECT_TRUE(ReadDirectorySync(util::GetDriveGrandRootPath()));
740 // Loading of about resource should not happen as it's offline.
741 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
743 // Load "My Drive".
744 EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
745 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
747 // Tests that cached data can be loaded even if the server is not reachable.
748 EXPECT_TRUE(EntryExists(base::FilePath(
749 FILE_PATH_LITERAL("drive/root/File1"))));
750 EXPECT_TRUE(EntryExists(base::FilePath(
751 FILE_PATH_LITERAL("drive/root/Dir1"))));
752 EXPECT_TRUE(EntryExists(base::FilePath(
753 FILE_PATH_LITERAL("drive/root/Dir1/File2"))));
754 EXPECT_TRUE(EntryExists(base::FilePath(
755 FILE_PATH_LITERAL("drive/root/Dir1/SubDir2"))));
756 EXPECT_TRUE(EntryExists(base::FilePath(
757 FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"))));
759 // Since the file system has at least succeeded to load cached snapshot,
760 // the file system should be able to start periodic refresh.
761 // To test it, call CheckForUpdates and verify it does try to check
762 // updates, which will cause directory changes.
763 fake_drive_service_->set_offline(false);
765 file_system_->CheckForUpdates();
767 content::RunAllBlockingPoolTasksUntilIdle();
768 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
769 EXPECT_EQ(1, fake_drive_service_->change_list_load_count());
771 ASSERT_LE(0u, mock_directory_observer_->changed_directories().size());
772 ASSERT_LE(1u, mock_directory_observer_->changed_files().size());
775 TEST_F(FileSystemTest, ReadDirectoryWhileRefreshing) {
776 // Use old timestamp so the fast fetch will be performed.
777 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
779 // The list of resources in "drive/root/Dir1" should be fetched.
780 EXPECT_TRUE(ReadDirectorySync(base::FilePath(
781 FILE_PATH_LITERAL("drive/root/Dir1"))));
782 EXPECT_EQ(1, fake_drive_service_->directory_load_count());
784 ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
787 TEST_F(FileSystemTest, GetResourceEntryNonExistentWhileRefreshing) {
788 // Use old timestamp so the fast fetch will be performed.
789 ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
791 // If an entry is not found, parent directory's resource list is fetched.
792 EXPECT_FALSE(GetResourceEntrySync(base::FilePath(
793 FILE_PATH_LITERAL("drive/root/Dir1/NonExistentFile"))));
794 EXPECT_EQ(1, fake_drive_service_->directory_load_count());
796 ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
799 TEST_F(FileSystemTest, CreateDirectoryByImplicitLoad) {
800 // Intentionally *not* calling LoadFullResourceList(), for testing that
801 // CreateDirectory ensures the resource list is loaded before it runs.
803 base::FilePath existing_directory(
804 FILE_PATH_LITERAL("drive/root/Directory 1"));
805 FileError error = FILE_ERROR_FAILED;
806 file_system_->CreateDirectory(
807 existing_directory,
808 true, // is_exclusive
809 false, // is_recursive
810 google_apis::test_util::CreateCopyResultCallback(&error));
811 content::RunAllBlockingPoolTasksUntilIdle();
813 // It should fail because is_exclusive is set to true.
814 EXPECT_EQ(FILE_ERROR_EXISTS, error);
817 TEST_F(FileSystemTest, CreateDirectoryRecursively) {
818 // Intentionally *not* calling LoadFullResourceList(), for testing that
819 // CreateDirectory ensures the resource list is loaded before it runs.
821 base::FilePath new_directory(
822 FILE_PATH_LITERAL("drive/root/Directory 1/a/b/c/d"));
823 FileError error = FILE_ERROR_FAILED;
824 file_system_->CreateDirectory(
825 new_directory,
826 true, // is_exclusive
827 true, // is_recursive
828 google_apis::test_util::CreateCopyResultCallback(&error));
829 content::RunAllBlockingPoolTasksUntilIdle();
831 EXPECT_EQ(FILE_ERROR_OK, error);
833 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(new_directory));
834 ASSERT_TRUE(entry);
835 EXPECT_TRUE(entry->file_info().is_directory());
838 TEST_F(FileSystemTest, ReadDirectoryAfterUpdateWhileLoading) {
839 // Simulate the situation that full feed fetching takes very long time,
840 // to test the recursive "fast fetch" feature is properly working.
841 fake_drive_service_->set_never_return_all_file_list(true);
843 // On the fake server, create the test directory.
844 scoped_ptr<google_apis::FileResource> parent;
846 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
847 fake_drive_service_->AddNewDirectory(
848 fake_drive_service_->GetRootResourceId(), "UpdateWhileLoadingTestDir",
849 AddNewDirectoryOptions(),
850 google_apis::test_util::CreateCopyResultCallback(&error, &parent));
851 base::RunLoop().RunUntilIdle();
852 ASSERT_EQ(google_apis::HTTP_CREATED, error);
855 // Fetch the directory. Currently it is empty.
856 scoped_ptr<ResourceEntryVector> before = ReadDirectorySync(base::FilePath(
857 FILE_PATH_LITERAL("drive/root/UpdateWhileLoadingTestDir")));
858 ASSERT_TRUE(before);
859 EXPECT_EQ(0u, before->size());
861 // Create a file in the test directory.
862 scoped_ptr<google_apis::FileResource> entry;
864 google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
865 fake_drive_service_->AddNewFile(
866 "text/plain",
867 "(dummy data)",
868 parent->file_id(),
869 "TestFile",
870 false, // shared_with_me
871 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
872 base::RunLoop().RunUntilIdle();
873 ASSERT_EQ(google_apis::HTTP_CREATED, error);
876 // Notify the update to the file system.
877 file_system_->CheckForUpdates();
879 // Read the directory once again. Although the full feed fetching is not yet
880 // finished, the "fast fetch" of the directory works and the refreshed content
881 // is returned.
882 scoped_ptr<ResourceEntryVector> after = ReadDirectorySync(base::FilePath(
883 FILE_PATH_LITERAL("drive/root/UpdateWhileLoadingTestDir")));
884 ASSERT_TRUE(after);
885 EXPECT_EQ(1u, after->size());
888 TEST_F(FileSystemTest, PinAndUnpin) {
889 ASSERT_TRUE(LoadFullResourceList());
891 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
893 // Get the file info.
894 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
895 ASSERT_TRUE(entry);
897 // Pin the file.
898 FileError error = FILE_ERROR_FAILED;
899 file_system_->Pin(file_path,
900 google_apis::test_util::CreateCopyResultCallback(&error));
901 content::RunAllBlockingPoolTasksUntilIdle();
902 EXPECT_EQ(FILE_ERROR_OK, error);
904 entry = GetResourceEntrySync(file_path);
905 ASSERT_TRUE(entry);
906 EXPECT_TRUE(entry->file_specific_info().cache_state().is_pinned());
907 EXPECT_TRUE(entry->file_specific_info().cache_state().is_present());
909 // Unpin the file.
910 error = FILE_ERROR_FAILED;
911 file_system_->Unpin(file_path,
912 google_apis::test_util::CreateCopyResultCallback(&error));
913 content::RunAllBlockingPoolTasksUntilIdle();
914 EXPECT_EQ(FILE_ERROR_OK, error);
916 entry = GetResourceEntrySync(file_path);
917 ASSERT_TRUE(entry);
918 EXPECT_FALSE(entry->file_specific_info().cache_state().is_pinned());
920 // Pinned file gets synced and it results in entry state changes.
921 ASSERT_EQ(0u, mock_directory_observer_->changed_directories().size());
922 ASSERT_EQ(1u, mock_directory_observer_->changed_files().size());
923 EXPECT_EQ(1u,
924 mock_directory_observer_->changed_files().CountDirectory(
925 base::FilePath(FILE_PATH_LITERAL("drive/root"))));
928 TEST_F(FileSystemTest, PinAndUnpin_NotSynced) {
929 ASSERT_TRUE(LoadFullResourceList());
931 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
933 // Get the file info.
934 scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
935 ASSERT_TRUE(entry);
937 // Unpin the file just after pinning. File fetch should be cancelled.
938 FileError error_pin = FILE_ERROR_FAILED;
939 file_system_->Pin(
940 file_path,
941 google_apis::test_util::CreateCopyResultCallback(&error_pin));
943 FileError error_unpin = FILE_ERROR_FAILED;
944 file_system_->Unpin(
945 file_path,
946 google_apis::test_util::CreateCopyResultCallback(&error_unpin));
948 content::RunAllBlockingPoolTasksUntilIdle();
949 EXPECT_EQ(FILE_ERROR_OK, error_pin);
950 EXPECT_EQ(FILE_ERROR_OK, error_unpin);
952 // No cache file available because the sync was cancelled by Unpin().
953 entry = GetResourceEntrySync(file_path);
954 ASSERT_TRUE(entry);
955 EXPECT_FALSE(entry->file_specific_info().cache_state().is_present());
958 TEST_F(FileSystemTest, GetAvailableSpace) {
959 FileError error = FILE_ERROR_OK;
960 int64 bytes_total;
961 int64 bytes_used;
962 file_system_->GetAvailableSpace(
963 google_apis::test_util::CreateCopyResultCallback(
964 &error, &bytes_total, &bytes_used));
965 content::RunAllBlockingPoolTasksUntilIdle();
966 EXPECT_EQ(6789012345LL, bytes_used);
967 EXPECT_EQ(9876543210LL, bytes_total);
970 TEST_F(FileSystemTest, MarkCacheFileAsMountedAndUnmounted) {
971 ASSERT_TRUE(LoadFullResourceList());
973 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
975 // Make the file cached.
976 FileError error = FILE_ERROR_FAILED;
977 base::FilePath file_path;
978 scoped_ptr<ResourceEntry> entry;
979 file_system_->GetFile(
980 file_in_root,
981 google_apis::test_util::CreateCopyResultCallback(
982 &error, &file_path, &entry));
983 content::RunAllBlockingPoolTasksUntilIdle();
984 EXPECT_EQ(FILE_ERROR_OK, error);
986 // Test for mounting.
987 error = FILE_ERROR_FAILED;
988 file_path.clear();
989 file_system_->MarkCacheFileAsMounted(
990 file_in_root,
991 google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
992 content::RunAllBlockingPoolTasksUntilIdle();
993 EXPECT_EQ(FILE_ERROR_OK, error);
995 // Cannot remove a cache entry while it's being mounted.
996 EXPECT_EQ(FILE_ERROR_IN_USE, cache_->Remove(entry->local_id()));
998 // Test for unmounting.
999 error = FILE_ERROR_FAILED;
1000 file_system_->MarkCacheFileAsUnmounted(
1001 file_path,
1002 google_apis::test_util::CreateCopyResultCallback(&error));
1003 content::RunAllBlockingPoolTasksUntilIdle();
1004 EXPECT_EQ(FILE_ERROR_OK, error);
1006 // Now able to remove the cache entry.
1007 EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(entry->local_id()));
1010 TEST_F(FileSystemTest, GetShareUrl) {
1011 ASSERT_TRUE(LoadFullResourceList());
1013 const base::FilePath kFileInRoot(FILE_PATH_LITERAL("drive/root/File 1.txt"));
1014 const GURL kEmbedOrigin("chrome-extension://test-id");
1016 // Try to fetch the URL for the sharing dialog.
1017 FileError error = FILE_ERROR_FAILED;
1018 GURL share_url;
1019 file_system_->GetShareUrl(
1020 kFileInRoot,
1021 kEmbedOrigin,
1022 google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
1023 content::RunAllBlockingPoolTasksUntilIdle();
1025 // Verify the share url to the sharing dialog.
1026 EXPECT_EQ(FILE_ERROR_OK, error);
1027 EXPECT_TRUE(share_url.is_valid());
1030 TEST_F(FileSystemTest, FreeDiskSpaceIfNeededFor) {
1031 ASSERT_TRUE(LoadFullResourceList());
1033 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
1035 // Make the file cached.
1036 FileError error = FILE_ERROR_FAILED;
1037 base::FilePath file_path;
1038 scoped_ptr<ResourceEntry> entry;
1039 file_system_->GetFile(file_in_root,
1040 google_apis::test_util::CreateCopyResultCallback(
1041 &error, &file_path, &entry));
1042 content::RunAllBlockingPoolTasksUntilIdle();
1043 EXPECT_EQ(FILE_ERROR_OK, error);
1044 ASSERT_TRUE(entry);
1045 EXPECT_TRUE(entry->file_specific_info().cache_state().is_present());
1047 bool available;
1048 file_system_->FreeDiskSpaceIfNeededFor(
1049 512LL << 40,
1050 google_apis::test_util::CreateCopyResultCallback(&available));
1051 content::RunAllBlockingPoolTasksUntilIdle();
1052 ASSERT_FALSE(available);
1054 entry = GetResourceEntrySync(file_in_root);
1055 ASSERT_TRUE(entry);
1056 EXPECT_FALSE(entry->file_specific_info().cache_state().is_present());
1059 } // namespace drive