Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / file_system_unittest.cc
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.
4
5 #include "chrome/browser/chromeos/drive/file_system.h"
6
7 #include <string>
8 #include <vector>
9
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"
32
33 namespace drive {
34 namespace {
35
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.
45     quit.Run();
46     return;
47   }
48
49   (*counter)++;
50   if (*counter >= expected_counter)
51     quit.Run();
52 }
53
54 // This class is used to record directory changes and examine them later.
55 class MockDirectoryChangeObserver : public FileSystemObserver {
56  public:
57   MockDirectoryChangeObserver() {}
58   virtual ~MockDirectoryChangeObserver() {}
59
60   // FileSystemObserver overrides.
61   virtual void OnDirectoryChanged(
62       const base::FilePath& directory_path) OVERRIDE {
63     changed_directories_.push_back(directory_path);
64   }
65
66   const std::vector<base::FilePath>& changed_directories() const {
67     return changed_directories_;
68   }
69
70  private:
71   std::vector<base::FilePath> changed_directories_;
72   DISALLOW_COPY_AND_ASSIGN(MockDirectoryChangeObserver);
73 };
74
75 }  // namespace
76
77 class FileSystemTest : public testing::Test {
78  protected:
79   virtual void SetUp() OVERRIDE {
80     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
81     pref_service_.reset(new TestingPrefServiceSimple);
82     test_util::RegisterDrivePrefs(pref_service_->registry());
83
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");
90
91     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
92
93     scheduler_.reset(new JobScheduler(pref_service_.get(),
94                                       logger_.get(),
95                                       fake_drive_service_.get(),
96                                       base::MessageLoopProxy::current().get()));
97
98     mock_directory_observer_.reset(new MockDirectoryChangeObserver);
99
100     SetUpResourceMetadataAndFileSystem();
101   }
102
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());
109
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(),
114         cache_dir,
115         base::MessageLoopProxy::current().get(),
116         fake_free_disk_space_getter_.get()));
117     ASSERT_TRUE(cache_->Initialize());
118
119     resource_metadata_.reset(new internal::ResourceMetadata(
120         metadata_storage_.get(), base::MessageLoopProxy::current()));
121     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
122
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(
126         pref_service_.get(),
127         logger_.get(),
128         cache_.get(),
129         fake_drive_service_.get(),
130         scheduler_.get(),
131         resource_metadata_.get(),
132         base::MessageLoopProxy::current().get(),
133         temp_file_dir));
134     file_system_->AddObserver(mock_directory_observer_.get());
135
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));
139   }
140
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;
148   }
149
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(
156         file_path,
157         google_apis::test_util::CreateCopyResultCallback(&error, &entry));
158     test_util::RunBlockingPoolTask();
159
160     return entry.Pass();
161   }
162
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(
170         file_path,
171         base::Bind(&AccumulateReadDirectoryResult,
172                    &error, entries.get(), &last_has_more));
173     test_util::RunBlockingPoolTask();
174     if (error != FILE_ERROR_OK)
175       entries.reset();
176     return entries.Pass();
177   }
178
179   // Used to implement ReadDirectorySync().
180   static void AccumulateReadDirectoryResult(
181       FileError* out_error,
182       ResourceEntryVector* out_entries,
183       bool* last_has_more,
184       FileError error,
185       scoped_ptr<ResourceEntryVector> entries,
186       bool has_more) {
187     EXPECT_TRUE(*last_has_more);
188     *out_error = error;
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());
193     } else {
194       EXPECT_FALSE(has_more);
195     }
196   }
197
198   // Returns true if an entry exists at |file_path|.
199   bool EntryExists(const base::FilePath& file_path) {
200     return GetResourceEntrySync(file_path);
201   }
202
203   // Flag for specifying the timestamp of the test filesystem cache.
204   enum SetUpTestFileSystemParam {
205     USE_OLD_TIMESTAMP,
206     USE_SERVER_TIMESTAMP,
207   };
208
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();
217
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()));
224
225     scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests>
226         resource_metadata(new internal::ResourceMetadata(
227             metadata_storage_.get(), base::MessageLoopProxy::current()));
228
229     ASSERT_EQ(FILE_ERROR_OK, resource_metadata->Initialize());
230
231     const int64 changestamp = param == USE_SERVER_TIMESTAMP ? 654321 : 1;
232     ASSERT_EQ(FILE_ERROR_OK,
233               resource_metadata->SetLargestChangestamp(changestamp));
234
235     // drive/root
236     ResourceEntry root;
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));
241
242     std::string local_id;
243
244     // drive/root/File1
245     ResourceEntry file1;
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));
253
254     // drive/root/Dir1
255     ResourceEntry dir1;
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;
262
263     // drive/root/Dir1/File2
264     ResourceEntry 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));
272
273     // drive/root/Dir1/SubDir2
274     ResourceEntry dir2;
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;
281
282     // drive/root/Dir1/SubDir2/File3
283     ResourceEntry 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));
291
292     // Recreate resource metadata.
293     SetUpResourceMetadataAndFileSystem();
294   }
295
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_;
301
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_;
307
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>
312       resource_metadata_;
313   scoped_ptr<FileSystem> file_system_;
314 };
315
316 TEST_F(FileSystemTest, DuplicatedAsyncInitialization) {
317   base::RunLoop loop;
318
319   int counter = 0;
320   const GetResourceEntryCallback& callback = base::Bind(
321       &AsyncInitializationCallback, &counter, 2, loop.QuitClosure());
322
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);
329
330   EXPECT_EQ(1, fake_drive_service_->resource_list_load_count());
331 }
332
333 TEST_F(FileSystemTest, GetGrandRootEntry) {
334   const base::FilePath kFilePath(FILE_PATH_LITERAL("drive"));
335   scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
336   ASSERT_TRUE(entry);
337   EXPECT_EQ(util::kDriveGrandRootLocalId, entry->local_id());
338 }
339
340 TEST_F(FileSystemTest, GetOtherDirEntry) {
341   const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/other"));
342   scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
343   ASSERT_TRUE(entry);
344   EXPECT_EQ(util::kDriveOtherDirLocalId, entry->local_id());
345 }
346
347 TEST_F(FileSystemTest, GetMyDriveRoot) {
348   const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root"));
349   scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
350   ASSERT_TRUE(entry);
351   EXPECT_EQ(fake_drive_service_->GetRootResourceId(), entry->resource_id());
352
353   EXPECT_EQ(1, fake_drive_service_->about_resource_load_count());
354
355   // After "fast fetch" is done, full resource list is fetched.
356   EXPECT_EQ(1, fake_drive_service_->resource_list_load_count());
357 }
358
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);
363
364   const base::FilePath kFilePath(
365       FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
366   scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
367   ASSERT_TRUE(entry);
368   EXPECT_EQ("file:subdirectory_file_1_id", entry->resource_id());
369
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());
373 }
374
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);
379   ASSERT_TRUE(entry);
380   EXPECT_EQ("document:5_document_resource_id", entry->resource_id());
381 }
382
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);
387   EXPECT_FALSE(entry);
388 }
389
390 TEST_F(FileSystemTest, GetExistingDirectory) {
391   const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/Directory 1"));
392   scoped_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
393   ASSERT_TRUE(entry);
394   ASSERT_EQ("folder:1_folder_resource_id", entry->resource_id());
395
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());
399 }
400
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);
406   ASSERT_TRUE(entry);
407   ASSERT_EQ("folder:sub_sub_directory_folder_id", entry->resource_id());
408 }
409
410 TEST_F(FileSystemTest, GetOrphanFile) {
411   ASSERT_TRUE(LoadFullResourceList());
412
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);
417   ASSERT_TRUE(entry);
418   EXPECT_EQ("file:1_orphanfile_resource_id", entry->resource_id());
419 }
420
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());
428
429   // The found three directories should be /drive/root, /drive/other and
430   // /drive/trash.
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)));
438 }
439
440 TEST_F(FileSystemTest, ReadDirectory_NonRootDirectory) {
441   // ReadDirectory() should kick off the resource list loading.
442   scoped_ptr<ResourceEntryVector> entries(
443       ReadDirectorySync(
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());
450 }
451
452 TEST_F(FileSystemTest, LoadFileSystemFromUpToDateCache) {
453   ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP));
454
455   // Kicks loading of cached file system and query for server update.
456   EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
457
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());
463
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());
470 }
471
472 TEST_F(FileSystemTest, LoadFileSystemFromCacheWhileOffline) {
473   ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_OLD_TIMESTAMP));
474
475   // Make GetResourceList fail for simulating offline situation. This will
476   // leave the file system "loaded from cache, but not synced with server"
477   // state.
478   fake_drive_service_->set_offline(true);
479
480   // Load the root.
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());
484
485   // Load "My Drive".
486   EXPECT_TRUE(ReadDirectorySync(util::GetDriveMyDriveRootPath()));
487   EXPECT_EQ(0, fake_drive_service_->about_resource_load_count());
488
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"))));
500
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);
506
507   file_system_->CheckForUpdates();
508
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());
512
513   ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
514 }
515
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();
520
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());
525
526   ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
527 }
528
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();
533
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());
538
539   ASSERT_LE(1u, mock_directory_observer_->changed_directories().size());
540 }
541
542 TEST_F(FileSystemTest, CreateDirectoryByImplicitLoad) {
543   // Intentionally *not* calling LoadFullResourceList(), for testing that
544   // CreateDirectory ensures the resource list is loaded before it runs.
545
546   base::FilePath existing_directory(
547       FILE_PATH_LITERAL("drive/root/Directory 1"));
548   FileError error = FILE_ERROR_FAILED;
549   file_system_->CreateDirectory(
550       existing_directory,
551       true,  // is_exclusive
552       false,  // is_recursive
553       google_apis::test_util::CreateCopyResultCallback(&error));
554   test_util::RunBlockingPoolTask();
555
556   // It should fail because is_exclusive is set to true.
557   EXPECT_EQ(FILE_ERROR_EXISTS, error);
558 }
559
560 TEST_F(FileSystemTest, CreateDirectoryRecursively) {
561   // Intentionally *not* calling LoadFullResourceList(), for testing that
562   // CreateDirectory ensures the resource list is loaded before it runs.
563
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(
568       new_directory,
569       true,  // is_exclusive
570       true,  // is_recursive
571       google_apis::test_util::CreateCopyResultCallback(&error));
572   test_util::RunBlockingPoolTask();
573
574   EXPECT_EQ(FILE_ERROR_OK, error);
575
576   scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(new_directory));
577   ASSERT_TRUE(entry);
578   EXPECT_TRUE(entry->file_info().is_directory());
579 }
580
581 TEST_F(FileSystemTest, PinAndUnpin) {
582   ASSERT_TRUE(LoadFullResourceList());
583
584   base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
585
586   // Get the file info.
587   scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
588   ASSERT_TRUE(entry);
589
590   // Pin the file.
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);
596
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());
601
602   // Unpin the file.
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);
608
609   EXPECT_TRUE(cache_->GetCacheEntry(entry->local_id(), &cache_entry));
610   EXPECT_FALSE(cache_entry.is_pinned());
611
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]);
616 }
617
618 TEST_F(FileSystemTest, PinAndUnpin_NotSynced) {
619   ASSERT_TRUE(LoadFullResourceList());
620
621   base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
622
623   // Get the file info.
624   scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_path));
625   ASSERT_TRUE(entry);
626
627   // Unpin the file just after pinning. File fetch should be cancelled.
628   FileError error_pin = FILE_ERROR_FAILED;
629   file_system_->Pin(
630       file_path,
631       google_apis::test_util::CreateCopyResultCallback(&error_pin));
632
633   FileError error_unpin = FILE_ERROR_FAILED;
634   file_system_->Unpin(
635       file_path,
636       google_apis::test_util::CreateCopyResultCallback(&error_unpin));
637
638   test_util::RunBlockingPoolTask();
639   EXPECT_EQ(FILE_ERROR_OK, error_pin);
640   EXPECT_EQ(FILE_ERROR_OK, error_unpin);
641
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));
645 }
646
647 TEST_F(FileSystemTest, GetAvailableSpace) {
648   FileError error = FILE_ERROR_OK;
649   int64 bytes_total;
650   int64 bytes_used;
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);
657 }
658
659 TEST_F(FileSystemTest, MarkCacheFileAsMountedAndUnmounted) {
660   ASSERT_TRUE(LoadFullResourceList());
661
662   base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
663   scoped_ptr<ResourceEntry> entry(GetResourceEntrySync(file_in_root));
664   ASSERT_TRUE(entry);
665
666   // Write to cache.
667   ASSERT_EQ(FILE_ERROR_OK, cache_->Store(
668       entry->local_id(),
669       entry->file_specific_info().md5(),
670       google_apis::test_util::GetTestFilePath("gdata/root_feed.json"),
671       internal::FileCache::FILE_OPERATION_COPY));
672
673   // Test for mounting.
674   FileError error = FILE_ERROR_FAILED;
675   base::FilePath file_path;
676   file_system_->MarkCacheFileAsMounted(
677       file_in_root,
678       google_apis::test_util::CreateCopyResultCallback(&error, &file_path));
679   test_util::RunBlockingPoolTask();
680   EXPECT_EQ(FILE_ERROR_OK, error);
681
682   // Cannot remove a cache entry while it's being mounted.
683   EXPECT_EQ(FILE_ERROR_IN_USE, cache_->Remove(entry->local_id()));
684
685   // Test for unmounting.
686   error = FILE_ERROR_FAILED;
687   file_system_->MarkCacheFileAsUnmounted(
688       file_path,
689       google_apis::test_util::CreateCopyResultCallback(&error));
690   test_util::RunBlockingPoolTask();
691   EXPECT_EQ(FILE_ERROR_OK, error);
692
693   // Now able to remove the cache entry.
694   EXPECT_EQ(FILE_ERROR_OK, cache_->Remove(entry->local_id()));
695 }
696
697 TEST_F(FileSystemTest, GetShareUrl) {
698   ASSERT_TRUE(LoadFullResourceList());
699
700   const base::FilePath kFileInRoot(FILE_PATH_LITERAL("drive/root/File 1.txt"));
701   const GURL kEmbedOrigin("chrome-extension://test-id");
702
703   // Try to fetch the URL for the sharing dialog.
704   FileError error = FILE_ERROR_FAILED;
705   GURL share_url;
706   file_system_->GetShareUrl(
707       kFileInRoot,
708       kEmbedOrigin,
709       google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
710   test_util::RunBlockingPoolTask();
711
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);
715 }
716
717 TEST_F(FileSystemTest, GetShareUrlNotAvailable) {
718   ASSERT_TRUE(LoadFullResourceList());
719
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");
723
724   // Try to fetch the URL for the sharing dialog.
725   FileError error = FILE_ERROR_FAILED;
726   GURL share_url;
727
728   file_system_->GetShareUrl(
729       kFileInRoot,
730       kEmbedOrigin,
731       google_apis::test_util::CreateCopyResultCallback(&error, &share_url));
732   test_util::RunBlockingPoolTask();
733
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());
737 }
738
739 }   // namespace drive