Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: chrome/browser/chromeos/gdata/gdata_file_system_unittest.cc

Issue 10874028: Rename GDataFileSystem* to DriveFileSystem* (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 <string>
6 #include <vector>
7
8 #include "base/bind.h"
9 #include "base/file_path.h"
10 #include "base/file_util.h"
11 #include "base/json/json_file_value_serializer.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h"
14 #include "base/path_service.h"
15 #include "base/scoped_temp_dir.h"
16 #include "base/stringprintf.h"
17 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/values.h"
19 #include "chrome/browser/chromeos/cros/cros_library.h"
20 #include "chrome/browser/chromeos/gdata/drive.pb.h"
21 #include "chrome/browser/chromeos/gdata/drive_api_parser.h"
22 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h"
23 #include "chrome/browser/chromeos/gdata/gdata_file_system.h"
24 #include "chrome/browser/chromeos/gdata/gdata_test_util.h"
25 #include "chrome/browser/chromeos/gdata/gdata_uploader.h"
26 #include "chrome/browser/chromeos/gdata/gdata_util.h"
27 #include "chrome/browser/chromeos/gdata/mock_directory_change_observer.h"
28 #include "chrome/browser/chromeos/gdata/mock_drive_cache_observer.h"
29 #include "chrome/browser/chromeos/gdata/mock_drive_service.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/test/base/testing_profile.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "content/public/test/test_browser_thread.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 using ::testing::AtLeast;
38 using ::testing::Eq;
39 using ::testing::NotNull;
40 using ::testing::Return;
41 using ::testing::StrictMock;
42 using ::testing::_;
43
44 namespace gdata {
45 namespace {
46
47 const char kSymLinkToDevNull[] = "/dev/null";
48
49 const int64 kLotsOfSpace = kMinFreeSpace * 10;
50
51 struct SearchResultPair {
52 const char* path;
53 const bool is_directory;
54 };
55
56 // Callback to GDataFileSystem::Search used in ContentSearch tests.
57 // Verifies returned vector of results.
58 void DriveSearchCallback(
59 MessageLoop* message_loop,
60 const SearchResultPair* expected_results,
61 size_t expected_results_size,
62 DriveFileError error,
63 const GURL& next_feed,
64 scoped_ptr<std::vector<SearchResultInfo> > results) {
65 ASSERT_TRUE(results.get());
66 ASSERT_EQ(expected_results_size, results->size());
67
68 for (size_t i = 0; i < results->size(); i++) {
69 EXPECT_EQ(FilePath(expected_results[i].path),
70 results->at(i).path);
71 EXPECT_EQ(expected_results[i].is_directory,
72 results->at(i).is_directory);
73 }
74
75 message_loop->Quit();
76 }
77
78 // Action used to set mock expectations for
79 // DriveServiceInterface::GetDocumentEntry().
80 ACTION_P2(MockGetDocumentEntry, status, value) {
81 base::MessageLoopProxy::current()->PostTask(FROM_HERE,
82 base::Bind(arg1, status, base::Passed(value)));
83 }
84
85 // Action used to set mock expectations for
86 // GDataUploaderInterface::UploadExistingFile().
87 ACTION_P4(MockUploadExistingFile,
88 error, gdata_path, local_file_path, document_entry) {
89 scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo);
90 upload_file_info->gdata_path = gdata_path;
91 upload_file_info->file_path = local_file_path;
92 upload_file_info->entry.reset(document_entry);
93 base::MessageLoopProxy::current()->PostTask(FROM_HERE,
94 base::Bind(arg5, error, base::Passed(&upload_file_info)));
95
96 const int kUploadId = 123;
97 return kUploadId;
98 }
99
100 // Action used to set mock expectations for
101 // GDataFileSystem::CopyDocument().
102 ACTION_P2(MockCopyDocument, status, value) {
103 base::MessageLoopProxy::current()->PostTask(
104 FROM_HERE,
105 base::Bind(arg2, status, base::Passed(value)));
106 }
107
108 // Returns the absolute path for a test file stored under
109 // chrome/test/data/chromeos/gdata.
110 FilePath GetTestFilePath(const FilePath::StringType& base_name) {
111 FilePath path;
112 std::string error;
113 PathService::Get(chrome::DIR_TEST_DATA, &path);
114 path = path.AppendASCII("chromeos")
115 .AppendASCII("gdata")
116 .AppendASCII(base_name.c_str());
117 EXPECT_TRUE(file_util::PathExists(path)) <<
118 "Couldn't find " << path.value();
119 return path;
120 }
121
122 // Loads a test JSON file as a base::Value.
123 base::Value* LoadJSONFile(const std::string& base_name) {
124 FilePath path = GetTestFilePath(base_name);
125
126 std::string error;
127 JSONFileValueSerializer serializer(path);
128 base::Value* value = serializer.Deserialize(NULL, &error);
129 EXPECT_TRUE(value) <<
130 "Parse error " << path.value() << ": " << error;
131 return value;
132 }
133
134 // Counts the number of files (not directories) in |entries|.
135 int CountFiles(const DriveEntryProtoVector& entries) {
136 int num_files = 0;
137 for (size_t i = 0; i < entries.size(); ++i) {
138 if (!entries[i].file_info().is_directory())
139 ++num_files;
140 }
141 return num_files;
142 }
143
144 } // namespace
145
146 class MockFreeDiskSpaceGetter : public FreeDiskSpaceGetterInterface {
147 public:
148 virtual ~MockFreeDiskSpaceGetter() {}
149 MOCK_CONST_METHOD0(AmountOfFreeDiskSpace, int64());
150 };
151
152 class MockGDataUploader : public GDataUploaderInterface {
153 public:
154 virtual ~MockGDataUploader() {}
155 // This function is not mockable by gmock.
156 virtual int UploadNewFile(
157 scoped_ptr<UploadFileInfo> upload_file_info) OVERRIDE {
158 // Set a document entry for an uploaded file.
159 // Used for TransferFileFromLocalToRemote_RegularFile test.
160 scoped_ptr<base::Value> value(LoadJSONFile("uploaded_file.json"));
161 scoped_ptr<DocumentEntry> document_entry(
162 DocumentEntry::ExtractAndParse(*value));
163 upload_file_info->entry = document_entry.Pass();
164
165 // Run the completion callback.
166 const UploadFileInfo::UploadCompletionCallback callback =
167 upload_file_info->completion_callback;
168 if (!callback.is_null())
169 callback.Run(DRIVE_FILE_OK, upload_file_info.Pass());
170
171 const int kUploadId = 123;
172 return kUploadId;
173 }
174
175 // This function is not mockable by gmock.
176 virtual int StreamExistingFile(
177 scoped_ptr<UploadFileInfo> upload_file_info) OVERRIDE { return 0; }
178
179 MOCK_METHOD6(UploadExistingFile,
180 int(const GURL& upload_location,
181 const FilePath& gdata_file_path,
182 const FilePath& local_file_path,
183 int64 file_size,
184 const std::string& content_type,
185 const UploadFileInfo::UploadCompletionCallback& callback));
186
187 MOCK_METHOD2(UpdateUpload, void(int upload_id,
188 content::DownloadItem* download));
189 MOCK_CONST_METHOD1(GetUploadedBytes, int64(int upload_id));
190 };
191
192 class MockDriveWebAppsRegistry : public DriveWebAppsRegistryInterface {
193 public:
194 virtual ~MockDriveWebAppsRegistry() {}
195
196 MOCK_METHOD3(GetWebAppsForFile, void(const FilePath& file,
197 const std::string& mime_type,
198 ScopedVector<DriveWebAppInfo>* apps));
199 MOCK_METHOD1(GetExtensionsForWebStoreApp,
200 std::set<std::string>(const std::string& web_store_id));
201 MOCK_METHOD1(UpdateFromFeed, void(const AccountMetadataFeed& metadata));
202 MOCK_METHOD1(UpdateFromApplicationList, void(const AppList& applist));
203 };
204
205 class GDataFileSystemTest : public testing::Test {
206 protected:
207 GDataFileSystemTest()
208 : ui_thread_(content::BrowserThread::UI, &message_loop_),
209 io_thread_(content::BrowserThread::IO),
210 cache_(NULL),
211 file_system_(NULL),
212 mock_drive_service_(NULL),
213 mock_webapps_registry_(NULL),
214 num_callback_invocations_(0),
215 expected_error_(DRIVE_FILE_OK),
216 expected_cache_state_(0),
217 expected_sub_dir_type_(DriveCache::CACHE_TYPE_META),
218 expected_success_(true),
219 expect_outgoing_symlink_(false),
220 root_feed_changestamp_(0) {
221 }
222
223 virtual void SetUp() OVERRIDE {
224 chromeos::CrosLibrary::Initialize(true /* use_stub */);
225 io_thread_.StartIOThread();
226
227 profile_.reset(new TestingProfile);
228
229 callback_helper_ = new CallbackHelper;
230
231 // Allocate and keep a pointer to the mock, and inject it into the
232 // GDataFileSystem object, which will own the mock object.
233 mock_drive_service_ = new StrictMock<MockDriveService>;
234
235 EXPECT_CALL(*mock_drive_service_, Initialize(profile_.get())).Times(1);
236
237 // Likewise, this will be owned by GDataFileSystem.
238 mock_free_disk_space_checker_ = new StrictMock<MockFreeDiskSpaceGetter>;
239 SetFreeDiskSpaceGetterForTesting(mock_free_disk_space_checker_);
240
241 scoped_refptr<base::SequencedWorkerPool> pool =
242 content::BrowserThread::GetBlockingPool();
243 blocking_task_runner_ =
244 pool->GetSequencedTaskRunner(pool->GetSequenceToken());
245
246 cache_ = DriveCache::CreateDriveCacheOnUIThread(
247 DriveCache::GetCacheRootPath(profile_.get()), blocking_task_runner_);
248
249 mock_uploader_.reset(new StrictMock<MockGDataUploader>);
250 mock_webapps_registry_.reset(new StrictMock<MockDriveWebAppsRegistry>);
251
252 ASSERT_FALSE(file_system_);
253 file_system_ = new GDataFileSystem(profile_.get(),
254 cache_,
255 mock_drive_service_,
256 mock_uploader_.get(),
257 mock_webapps_registry_.get(),
258 blocking_task_runner_);
259
260 mock_cache_observer_.reset(new StrictMock<MockDriveCacheObserver>);
261 cache_->AddObserver(mock_cache_observer_.get());
262
263 mock_directory_observer_.reset(new StrictMock<MockDirectoryChangeObserver>);
264 file_system_->AddObserver(mock_directory_observer_.get());
265
266 file_system_->Initialize();
267 cache_->RequestInitializeOnUIThreadForTesting();
268 test_util::RunBlockingPoolTask();
269 }
270
271 virtual void TearDown() OVERRIDE {
272 ASSERT_TRUE(file_system_);
273 EXPECT_CALL(*mock_drive_service_, CancelAll()).Times(1);
274 delete file_system_;
275 file_system_ = NULL;
276 delete mock_drive_service_;
277 mock_drive_service_ = NULL;
278 SetFreeDiskSpaceGetterForTesting(NULL);
279 cache_->DestroyOnUIThread();
280 // The cache destruction requires to post a task to the blocking pool.
281 test_util::RunBlockingPoolTask();
282
283 profile_.reset(NULL);
284 chromeos::CrosLibrary::Shutdown();
285 }
286
287 // Loads test json file as root ("/drive") element.
288 void LoadRootFeedDocument(const std::string& filename) {
289 LoadChangeFeed(filename, 0);
290 }
291
292 void LoadChangeFeed(const std::string& filename,
293 int largest_changestamp) {
294 std::string error;
295 scoped_ptr<Value> document(LoadJSONFile(filename));
296 ASSERT_TRUE(document.get());
297 ASSERT_TRUE(document->GetType() == Value::TYPE_DICTIONARY);
298 scoped_ptr<DocumentFeed> document_feed(
299 DocumentFeed::ExtractAndParse(*document));
300 ASSERT_TRUE(document_feed.get());
301 std::vector<DocumentFeed*> feed_list;
302 feed_list.push_back(document_feed.get());
303 ASSERT_TRUE(UpdateContent(feed_list, largest_changestamp));
304 }
305
306 void AddDirectoryFromFile(const FilePath& directory_path,
307 const std::string& filename) {
308 std::string error;
309 scoped_ptr<Value> atom(LoadJSONFile(filename));
310 ASSERT_TRUE(atom.get());
311 ASSERT_TRUE(atom->GetType() == Value::TYPE_DICTIONARY);
312
313 DictionaryValue* dict_value = NULL;
314 Value* entry_value = NULL;
315 ASSERT_TRUE(atom->GetAsDictionary(&dict_value));
316 ASSERT_TRUE(dict_value->Get("entry", &entry_value));
317
318 DictionaryValue* entry_dict = NULL;
319 ASSERT_TRUE(entry_value->GetAsDictionary(&entry_dict));
320
321 // Tweak entry title to match the last segment of the directory path
322 // (new directory name).
323 std::vector<FilePath::StringType> dir_parts;
324 directory_path.GetComponents(&dir_parts);
325 entry_dict->SetString("title.$t", dir_parts[dir_parts.size() - 1]);
326
327 ASSERT_EQ(file_system_->AddNewDirectory(directory_path.DirName(),
328 entry_value),
329 DRIVE_FILE_OK)
330 << "Failed adding "
331 << directory_path.DirName().value();
332 }
333
334 // Updates the content of directory under |directory_path| with parsed feed
335 // |value|.
336 bool UpdateContent(const std::vector<DocumentFeed*>& list,
337 int largest_changestamp) {
338 GURL unused;
339 return file_system_->UpdateFromFeedForTesting(
340 list,
341 largest_changestamp,
342 root_feed_changestamp_++) == DRIVE_FILE_OK;
343 }
344
345 bool RemoveEntry(const FilePath& file_path) {
346 return file_system_->RemoveEntryAndCacheLocally(file_path) ==
347 DRIVE_FILE_OK;
348 }
349
350 FilePath GetCachePathForFile(const std::string& resource_id,
351 const std::string& md5) {
352 return cache_->GetCacheFilePath(resource_id,
353 md5,
354 DriveCache::CACHE_TYPE_TMP,
355 DriveCache::CACHED_FILE_FROM_SERVER);
356 }
357
358 // Gets entry info by path synchronously.
359 scoped_ptr<DriveEntryProto> GetEntryInfoByPathSync(
360 const FilePath& file_path) {
361 file_system_->GetEntryInfoByPath(
362 file_path,
363 base::Bind(&CallbackHelper::GetEntryInfoCallback,
364 callback_helper_.get()));
365 test_util::RunBlockingPoolTask();
366
367 return callback_helper_->entry_proto_.Pass();
368 }
369
370 // Gets directory info by path synchronously.
371 scoped_ptr<DriveEntryProtoVector> ReadDirectoryByPathSync(
372 const FilePath& file_path) {
373 file_system_->ReadDirectoryByPath(
374 file_path,
375 base::Bind(&CallbackHelper::ReadDirectoryCallback,
376 callback_helper_.get()));
377 test_util::RunBlockingPoolTask();
378
379 return callback_helper_->directory_entries_.Pass();
380 }
381
382 // Returns true if an entry exists at |file_path|.
383 bool EntryExists(const FilePath& file_path) {
384 return GetEntryInfoByPathSync(file_path).get();
385 }
386
387
388 // Gets the resource ID of |file_path|. Returns an empty string if not found.
389 std::string GetResourceIdByPath(const FilePath& file_path) {
390 scoped_ptr<DriveEntryProto> entry_proto =
391 GetEntryInfoByPathSync(file_path);
392 if (entry_proto.get())
393 return entry_proto->resource_id();
394 else
395 return "";
396 }
397
398 // Helper function to call GetCacheEntry from origin thread.
399 bool GetCacheEntryFromOriginThread(const std::string& resource_id,
400 const std::string& md5,
401 DriveCacheEntry* cache_entry) {
402 bool result = false;
403 blocking_task_runner_->PostTask(
404 FROM_HERE,
405 base::Bind(&GDataFileSystemTest::GetCacheEntryFromOriginThreadInternal,
406 base::Unretained(this),
407 resource_id,
408 md5,
409 cache_entry,
410 &result));
411 test_util::RunBlockingPoolTask();
412 return result;
413 }
414
415 // Used to implement GetCacheEntry.
416 void GetCacheEntryFromOriginThreadInternal(
417 const std::string& resource_id,
418 const std::string& md5,
419 DriveCacheEntry* cache_entry,
420 bool* result) {
421 *result = cache_->GetCacheEntry(resource_id, md5, cache_entry);
422 }
423
424 // Returns true if the cache entry exists for the given resource ID and MD5.
425 bool CacheEntryExists(const std::string& resource_id,
426 const std::string& md5) {
427 DriveCacheEntry cache_entry;
428 return GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry);
429 }
430
431 // Returns true if the cache file exists for the given resource ID and MD5.
432 bool CacheFileExists(const std::string& resource_id,
433 const std::string& md5) {
434 const FilePath file_path = cache_->GetCacheFilePath(
435 resource_id,
436 md5,
437 DriveCache::CACHE_TYPE_TMP,
438 DriveCache::CACHED_FILE_FROM_SERVER);
439 return file_util::PathExists(file_path);
440 }
441
442 void TestStoreToCache(
443 const std::string& resource_id,
444 const std::string& md5,
445 const FilePath& source_path,
446 DriveFileError expected_error,
447 int expected_cache_state,
448 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
449 expected_error_ = expected_error;
450 expected_cache_state_ = expected_cache_state;
451 expected_sub_dir_type_ = expected_sub_dir_type;
452
453 cache_->StoreOnUIThread(
454 resource_id, md5, source_path,
455 DriveCache::FILE_OPERATION_COPY,
456 base::Bind(&GDataFileSystemTest::VerifyCacheFileState,
457 base::Unretained(this)));
458
459 test_util::RunBlockingPoolTask();
460 }
461
462 void TestPin(
463 const std::string& resource_id,
464 const std::string& md5,
465 DriveFileError expected_error,
466 int expected_cache_state,
467 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
468 expected_error_ = expected_error;
469 expected_cache_state_ = expected_cache_state;
470 expected_sub_dir_type_ = expected_sub_dir_type;
471
472 cache_->PinOnUIThread(
473 resource_id, md5,
474 base::Bind(&GDataFileSystemTest::VerifyCacheFileState,
475 base::Unretained(this)));
476
477 test_util::RunBlockingPoolTask();
478 }
479
480 void TestMarkDirty(
481 const std::string& resource_id,
482 const std::string& md5,
483 DriveFileError expected_error,
484 int expected_cache_state,
485 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
486 expected_error_ = expected_error;
487 expected_cache_state_ = expected_cache_state;
488 expected_sub_dir_type_ = expected_sub_dir_type;
489 expect_outgoing_symlink_ = false;
490
491 cache_->MarkDirtyOnUIThread(
492 resource_id, md5,
493 base::Bind(&GDataFileSystemTest::VerifyMarkDirty,
494 base::Unretained(this)));
495
496 test_util::RunBlockingPoolTask();
497 }
498
499 void VerifyMarkDirty(DriveFileError error,
500 const std::string& resource_id,
501 const std::string& md5,
502 const FilePath& cache_file_path) {
503 VerifyCacheFileState(error, resource_id, md5);
504
505 // Verify filename of |cache_file_path|.
506 if (error == DRIVE_FILE_OK) {
507 FilePath base_name = cache_file_path.BaseName();
508 EXPECT_EQ(util::EscapeCacheFileName(resource_id) +
509 FilePath::kExtensionSeparator +
510 "local",
511 base_name.value());
512 } else {
513 EXPECT_TRUE(cache_file_path.empty());
514 }
515 }
516
517 void TestCommitDirty(
518 const std::string& resource_id,
519 const std::string& md5,
520 DriveFileError expected_error,
521 int expected_cache_state,
522 DriveCache::CacheSubDirectoryType expected_sub_dir_type) {
523 expected_error_ = expected_error;
524 expected_cache_state_ = expected_cache_state;
525 expected_sub_dir_type_ = expected_sub_dir_type;
526 expect_outgoing_symlink_ = true;
527
528 cache_->CommitDirtyOnUIThread(
529 resource_id, md5,
530 base::Bind(&GDataFileSystemTest::VerifyCacheFileState,
531 base::Unretained(this)));
532
533 test_util::RunBlockingPoolTask();
534 }
535
536 // Verify the file identified by |resource_id| and |md5| is in the expected
537 // cache state after |OpenFile|, that is, marked dirty and has no outgoing
538 // symlink, etc.
539 void VerifyCacheStateAfterOpenFile(DriveFileError error,
540 const std::string& resource_id,
541 const std::string& md5,
542 const FilePath& cache_file_path) {
543 expected_error_ = DRIVE_FILE_OK;
544 expected_cache_state_ = (test_util::TEST_CACHE_STATE_PRESENT |
545 test_util::TEST_CACHE_STATE_DIRTY |
546 test_util::TEST_CACHE_STATE_PERSISTENT);
547 expected_sub_dir_type_ = DriveCache::CACHE_TYPE_PERSISTENT;
548 expect_outgoing_symlink_ = false;
549 VerifyMarkDirty(error, resource_id, md5, cache_file_path);
550 }
551
552 // Verify the file identified by |resource_id| and |md5| is in the expected
553 // cache state after |CloseFile|, that is, marked dirty and has an outgoing
554 // symlink, etc.
555 void VerifyCacheStateAfterCloseFile(DriveFileError error,
556 const std::string& resource_id,
557 const std::string& md5) {
558 expected_error_ = DRIVE_FILE_OK;
559 expected_cache_state_ = (test_util::TEST_CACHE_STATE_PRESENT |
560 test_util::TEST_CACHE_STATE_DIRTY |
561 test_util::TEST_CACHE_STATE_PERSISTENT);
562 expected_sub_dir_type_ = DriveCache::CACHE_TYPE_PERSISTENT;
563 expect_outgoing_symlink_ = true;
564 VerifyCacheFileState(error, resource_id, md5);
565 }
566
567 void VerifyCacheFileState(DriveFileError error,
568 const std::string& resource_id,
569 const std::string& md5) {
570 ++num_callback_invocations_;
571
572 EXPECT_EQ(expected_error_, error);
573
574 // Verify cache map.
575 DriveCacheEntry cache_entry;
576 const bool cache_entry_found =
577 GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry);
578 if (test_util::ToCacheEntry(expected_cache_state_).is_present() ||
579 test_util::ToCacheEntry(expected_cache_state_).is_pinned()) {
580 ASSERT_TRUE(cache_entry_found);
581 EXPECT_TRUE(test_util::CacheStatesEqual(
582 test_util::ToCacheEntry(expected_cache_state_),
583 cache_entry));
584 EXPECT_EQ(expected_sub_dir_type_,
585 DriveCache::GetSubDirectoryType(cache_entry));
586 } else {
587 EXPECT_FALSE(cache_entry_found);
588 }
589
590 // Verify actual cache file.
591 FilePath dest_path = cache_->GetCacheFilePath(
592 resource_id,
593 md5,
594 test_util::ToCacheEntry(expected_cache_state_).is_pinned() ||
595 test_util::ToCacheEntry(expected_cache_state_).is_dirty() ?
596 DriveCache::CACHE_TYPE_PERSISTENT :
597 DriveCache::CACHE_TYPE_TMP,
598 test_util::ToCacheEntry(expected_cache_state_).is_dirty() ?
599 DriveCache::CACHED_FILE_LOCALLY_MODIFIED :
600 DriveCache::CACHED_FILE_FROM_SERVER);
601 bool exists = file_util::PathExists(dest_path);
602 if (test_util::ToCacheEntry(expected_cache_state_).is_present())
603 EXPECT_TRUE(exists);
604 else
605 EXPECT_FALSE(exists);
606
607 // Verify symlink in pinned dir.
608 FilePath symlink_path = cache_->GetCacheFilePath(
609 resource_id,
610 std::string(),
611 DriveCache::CACHE_TYPE_PINNED,
612 DriveCache::CACHED_FILE_FROM_SERVER);
613 // Check that pin symlink exists, without dereferencing to target path.
614 exists = file_util::IsLink(symlink_path);
615 if (test_util::ToCacheEntry(expected_cache_state_).is_pinned()) {
616 EXPECT_TRUE(exists);
617 FilePath target_path;
618 EXPECT_TRUE(file_util::ReadSymbolicLink(symlink_path, &target_path));
619 if (test_util::ToCacheEntry(expected_cache_state_).is_present())
620 EXPECT_EQ(dest_path, target_path);
621 else
622 EXPECT_EQ(kSymLinkToDevNull, target_path.value());
623 } else {
624 EXPECT_FALSE(exists);
625 }
626
627 // Verify symlink in outgoing dir.
628 symlink_path = cache_->GetCacheFilePath(
629 resource_id,
630 std::string(),
631 DriveCache::CACHE_TYPE_OUTGOING,
632 DriveCache::CACHED_FILE_FROM_SERVER);
633 // Check that outgoing symlink exists, without dereferencing to target path.
634 exists = file_util::IsLink(symlink_path);
635 if (expect_outgoing_symlink_ &&
636 test_util::ToCacheEntry(expected_cache_state_).is_dirty()) {
637 EXPECT_TRUE(exists);
638 FilePath target_path;
639 EXPECT_TRUE(file_util::ReadSymbolicLink(symlink_path, &target_path));
640 EXPECT_TRUE(target_path.value() != kSymLinkToDevNull);
641 if (test_util::ToCacheEntry(expected_cache_state_).is_present())
642 EXPECT_EQ(dest_path, target_path);
643 } else {
644 EXPECT_FALSE(exists);
645 }
646 }
647
648 void SetExpectationsForGetDocumentEntry(scoped_ptr<base::Value>* document,
649 const std::string& resource_id) {
650 EXPECT_CALL(*mock_drive_service_, GetDocumentEntry(resource_id, _))
651 .WillOnce(MockGetDocumentEntry(gdata::HTTP_SUCCESS, document));
652 }
653
654 // Loads serialized proto file from GCache, and makes sure the root
655 // filesystem has a root at 'drive'
656 void TestLoadMetadataFromCache() {
657 file_system_->LoadRootFeedFromCacheForTesting();
658 test_util::RunBlockingPoolTask();
659 }
660
661 // Creates a proto file representing a filesystem with directories:
662 // drive, drive/Dir1, drive/Dir1/SubDir2
663 // and files
664 // drive/File1, drive/Dir1/File2, drive/Dir1/SubDir2/File3.
665 // Sets the changestamp to 654321, equal to that of "account_metadata.json"
666 // test data, indicating the cache is holding the latest file system info.
667 void SaveTestFileSystem() {
668 DriveRootDirectoryProto root;
669 root.set_version(kProtoVersion);
670 root.set_largest_changestamp(654321);
671 DriveDirectoryProto* root_dir = root.mutable_gdata_directory();
672 DriveEntryProto* dir_base = root_dir->mutable_gdata_entry();
673 PlatformFileInfoProto* platform_info = dir_base->mutable_file_info();
674 dir_base->set_title("drive");
675 dir_base->set_resource_id(kDriveRootDirectoryResourceId);
676 dir_base->set_upload_url("http://resumable-create-media/1");
677 platform_info->set_is_directory(true);
678
679 // drive/File1
680 DriveEntryProto* file = root_dir->add_child_files();
681 file->set_title("File1");
682 file->set_resource_id("resource_id:File1");
683 file->set_upload_url("http://resumable-edit-media/1");
684 file->mutable_file_specific_info()->set_file_md5("md5");
685 platform_info = file->mutable_file_info();
686 platform_info->set_is_directory(false);
687 platform_info->set_size(1048576);
688
689 // drive/Dir1
690 DriveDirectoryProto* dir1 = root_dir->add_child_directories();
691 dir_base = dir1->mutable_gdata_entry();
692 dir_base->set_title("Dir1");
693 dir_base->set_resource_id("resource_id:Dir1");
694 dir_base->set_upload_url("http://resumable-create-media/2");
695 platform_info = dir_base->mutable_file_info();
696 platform_info->set_is_directory(true);
697
698 // drive/Dir1/File2
699 file = dir1->add_child_files();
700 file->set_title("File2");
701 file->set_resource_id("resource_id:File2");
702 file->set_upload_url("http://resumable-edit-media/2");
703 file->mutable_file_specific_info()->set_file_md5("md5");
704 platform_info = file->mutable_file_info();
705 platform_info->set_is_directory(false);
706 platform_info->set_size(555);
707
708 // drive/Dir1/SubDir2
709 DriveDirectoryProto* dir2 = dir1->add_child_directories();
710 dir_base = dir2->mutable_gdata_entry();
711 dir_base->set_title("SubDir2");
712 dir_base->set_resource_id("resource_id:SubDir2");
713 dir_base->set_upload_url("http://resumable-create-media/3");
714 platform_info = dir_base->mutable_file_info();
715 platform_info->set_is_directory(true);
716
717 // drive/Dir1/SubDir2/File3
718 file = dir2->add_child_files();
719 file->set_title("File3");
720 file->set_resource_id("resource_id:File3");
721 file->set_upload_url("http://resumable-edit-media/3");
722 file->mutable_file_specific_info()->set_file_md5("md5");
723 platform_info = file->mutable_file_info();
724 platform_info->set_is_directory(false);
725 platform_info->set_size(12345);
726
727 // Write this proto out to GCache/vi/meta/file_system.pb
728 std::string serialized_proto;
729 ASSERT_TRUE(root.SerializeToString(&serialized_proto));
730 ASSERT_TRUE(!serialized_proto.empty());
731
732 FilePath cache_dir_path = profile_->GetPath().Append(
733 FILE_PATH_LITERAL("GCache/v1/meta/"));
734 ASSERT_TRUE(file_util::CreateDirectory(cache_dir_path));
735 const int file_size = static_cast<int>(serialized_proto.length());
736 ASSERT_EQ(file_util::WriteFile(cache_dir_path.Append("file_system.pb"),
737 serialized_proto.data(), file_size), file_size);
738 }
739
740 // Verifies that |file_path| is a valid JSON file for the hosted document
741 // associated with |entry| (i.e. |url| and |resource_id| match).
742 void VerifyHostedDocumentJSONFile(const DriveEntryProto& entry_proto,
743 const FilePath& file_path) {
744 std::string error;
745 JSONFileValueSerializer serializer(file_path);
746 scoped_ptr<Value> value(serializer.Deserialize(NULL, &error));
747 ASSERT_TRUE(value.get()) << "Parse error " << file_path.value()
748 << ": " << error;
749 DictionaryValue* dict_value = NULL;
750 ASSERT_TRUE(value->GetAsDictionary(&dict_value));
751
752 std::string edit_url, resource_id;
753 EXPECT_TRUE(dict_value->GetString("url", &edit_url));
754 EXPECT_TRUE(dict_value->GetString("resource_id", &resource_id));
755
756 EXPECT_EQ(entry_proto.file_specific_info().alternate_url(),
757 edit_url);
758 EXPECT_EQ(entry_proto.resource_id(), resource_id);
759 }
760
761 // This is used as a helper for registering callbacks that need to be
762 // RefCountedThreadSafe, and a place where we can fetch results from various
763 // operations.
764 class CallbackHelper
765 : public base::RefCountedThreadSafe<CallbackHelper> {
766 public:
767 CallbackHelper()
768 : last_error_(DRIVE_FILE_OK),
769 quota_bytes_total_(0),
770 quota_bytes_used_(0),
771 entry_proto_(NULL) {}
772
773 virtual void GetFileCallback(DriveFileError error,
774 const FilePath& file_path,
775 const std::string& mime_type,
776 DriveFileType file_type) {
777 last_error_ = error;
778 download_path_ = file_path;
779 mime_type_ = mime_type;
780 file_type_ = file_type;
781 }
782
783 virtual void FileOperationCallback(DriveFileError error) {
784 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
785
786 last_error_ = error;
787 }
788
789 virtual void GetAvailableSpaceCallback(DriveFileError error,
790 int64 bytes_total,
791 int64 bytes_used) {
792 last_error_ = error;
793 quota_bytes_total_ = bytes_total;
794 quota_bytes_used_ = bytes_used;
795 }
796
797 virtual void OpenFileCallback(DriveFileError error,
798 const FilePath& file_path) {
799 last_error_ = error;
800 opened_file_path_ = file_path;
801 MessageLoop::current()->Quit();
802 }
803
804 virtual void CloseFileCallback(DriveFileError error) {
805 last_error_ = error;
806 MessageLoop::current()->Quit();
807 }
808
809 virtual void GetEntryInfoCallback(
810 DriveFileError error,
811 scoped_ptr<DriveEntryProto> entry_proto) {
812 last_error_ = error;
813 entry_proto_ = entry_proto.Pass();
814 }
815
816 virtual void ReadDirectoryCallback(
817 DriveFileError error,
818 bool /* hide_hosted_documents */,
819 scoped_ptr<DriveEntryProtoVector> entries) {
820 last_error_ = error;
821 directory_entries_ = entries.Pass();
822 }
823
824 DriveFileError last_error_;
825 FilePath download_path_;
826 FilePath opened_file_path_;
827 std::string mime_type_;
828 DriveFileType file_type_;
829 int64 quota_bytes_total_;
830 int64 quota_bytes_used_;
831 scoped_ptr<DriveEntryProto> entry_proto_;
832 scoped_ptr<DriveEntryProtoVector> directory_entries_;
833
834 protected:
835 virtual ~CallbackHelper() {}
836
837 private:
838 friend class base::RefCountedThreadSafe<CallbackHelper>;
839 };
840
841 MessageLoopForUI message_loop_;
842 // The order of the test threads is important, do not change the order.
843 // See also content/browser/browser_thread_impl.cc.
844 content::TestBrowserThread ui_thread_;
845 content::TestBrowserThread io_thread_;
846 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
847 scoped_ptr<TestingProfile> profile_;
848 scoped_refptr<CallbackHelper> callback_helper_;
849 DriveCache* cache_;
850 scoped_ptr<StrictMock<MockGDataUploader> > mock_uploader_;
851 GDataFileSystem* file_system_;
852 StrictMock<MockDriveService>* mock_drive_service_;
853 scoped_ptr<StrictMock<MockDriveWebAppsRegistry> > mock_webapps_registry_;
854 StrictMock<MockFreeDiskSpaceGetter>* mock_free_disk_space_checker_;
855 scoped_ptr<StrictMock<MockDriveCacheObserver> > mock_cache_observer_;
856 scoped_ptr<StrictMock<MockDirectoryChangeObserver> > mock_directory_observer_;
857
858 int num_callback_invocations_;
859 DriveFileError expected_error_;
860 int expected_cache_state_;
861 DriveCache::CacheSubDirectoryType expected_sub_dir_type_;
862 bool expected_success_;
863 bool expect_outgoing_symlink_;
864 std::string expected_file_extension_;
865 int root_feed_changestamp_;
866 static bool cros_initialized_;
867 };
868
869 bool GDataFileSystemTest::cros_initialized_ = false;
870
871 void AsyncInitializationCallback(
872 int* counter,
873 int expected_counter,
874 const FilePath& expected_file_path,
875 MessageLoop* message_loop,
876 DriveFileError error,
877 scoped_ptr<DriveEntryProto> entry_proto) {
878 ASSERT_EQ(DRIVE_FILE_OK, error);
879 ASSERT_TRUE(entry_proto.get());
880 ASSERT_TRUE(entry_proto->file_info().is_directory());
881 EXPECT_EQ(expected_file_path.value(), entry_proto->base_name());
882
883 (*counter)++;
884 if (*counter >= expected_counter)
885 message_loop->Quit();
886 }
887
888 TEST_F(GDataFileSystemTest, DuplicatedAsyncInitialization) {
889 int counter = 0;
890 GetEntryInfoCallback callback = base::Bind(
891 &AsyncInitializationCallback,
892 &counter,
893 2,
894 FilePath(FILE_PATH_LITERAL("drive")),
895 &message_loop_);
896
897 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
898 EXPECT_CALL(*mock_drive_service_,
899 GetDocuments(Eq(GURL()), _, _, _, _)).Times(1);
900
901 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
902
903 file_system_->GetEntryInfoByPath(
904 FilePath(FILE_PATH_LITERAL("drive")), callback);
905 file_system_->GetEntryInfoByPath(
906 FilePath(FILE_PATH_LITERAL("drive")), callback);
907 message_loop_.Run(); // Wait to get our result
908 EXPECT_EQ(2, counter);
909 }
910
911 TEST_F(GDataFileSystemTest, SearchRootDirectory) {
912 LoadRootFeedDocument("root_feed.json");
913
914 const FilePath kFilePath = FilePath(FILE_PATH_LITERAL("drive"));
915 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(
916 FilePath(FILE_PATH_LITERAL(kFilePath)));
917 ASSERT_TRUE(entry.get());
918 EXPECT_EQ(kDriveRootDirectoryResourceId, entry->resource_id());
919 }
920
921 TEST_F(GDataFileSystemTest, SearchExistingFile) {
922 LoadRootFeedDocument("root_feed.json");
923
924 const FilePath kFilePath = FilePath(
925 FILE_PATH_LITERAL("drive/File 1.txt"));
926 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
927 ASSERT_TRUE(entry.get());
928 EXPECT_EQ("file:2_file_resource_id", entry->resource_id());
929 }
930
931 TEST_F(GDataFileSystemTest, SearchExistingDocument) {
932 LoadRootFeedDocument("root_feed.json");
933
934 const FilePath kFilePath = FilePath(
935 FILE_PATH_LITERAL("drive/Document 1.gdoc"));
936 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
937 ASSERT_TRUE(entry.get());
938 EXPECT_EQ("document:5_document_resource_id", entry->resource_id());
939 }
940
941 TEST_F(GDataFileSystemTest, SearchNonExistingFile) {
942 LoadRootFeedDocument("root_feed.json");
943
944 const FilePath kFilePath = FilePath(
945 FILE_PATH_LITERAL("drive/nonexisting.file"));
946 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
947 ASSERT_FALSE(entry.get());
948 }
949
950 TEST_F(GDataFileSystemTest, SearchEncodedFileNames) {
951 LoadRootFeedDocument("root_feed.json");
952
953 const FilePath kFilePath1 = FilePath(
954 FILE_PATH_LITERAL("drive/Slash / in file 1.txt"));
955 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath1);
956 ASSERT_FALSE(entry.get());
957
958 const FilePath kFilePath2 = FilePath::FromUTF8Unsafe(
959 "drive/Slash \xE2\x88\x95 in file 1.txt");
960 entry = GetEntryInfoByPathSync(kFilePath2);
961 ASSERT_TRUE(entry.get());
962 EXPECT_EQ("file:slash_file_resource_id", entry->resource_id());
963
964 const FilePath kFilePath3 = FilePath::FromUTF8Unsafe(
965 "drive/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt");
966 entry = GetEntryInfoByPathSync(kFilePath3);
967 ASSERT_TRUE(entry.get());
968 EXPECT_EQ("file:slash_subdir_file", entry->resource_id());
969 }
970
971 TEST_F(GDataFileSystemTest, SearchEncodedFileNamesLoadingRoot) {
972 LoadRootFeedDocument("root_feed.json");
973
974 const FilePath kFilePath1 = FilePath(
975 FILE_PATH_LITERAL("drive/Slash / in file 1.txt"));
976 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath1);
977 ASSERT_FALSE(entry.get());
978
979 const FilePath kFilePath2 = FilePath::FromUTF8Unsafe(
980 "drive/Slash \xE2\x88\x95 in file 1.txt");
981 entry = GetEntryInfoByPathSync(kFilePath2);
982 ASSERT_TRUE(entry.get());
983 EXPECT_EQ("file:slash_file_resource_id", entry->resource_id());
984
985 const FilePath kFilePath3 = FilePath::FromUTF8Unsafe(
986 "drive/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt");
987 entry = GetEntryInfoByPathSync(kFilePath3);
988 ASSERT_TRUE(entry.get());
989 EXPECT_EQ("file:slash_subdir_file", entry->resource_id());
990 }
991
992 TEST_F(GDataFileSystemTest, SearchDuplicateNames) {
993 LoadRootFeedDocument("root_feed.json");
994
995 const FilePath kFilePath1 = FilePath(
996 FILE_PATH_LITERAL("drive/Duplicate Name.txt"));
997 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath1);
998 ASSERT_TRUE(entry.get());
999 EXPECT_EQ("file:3_file_resource_id", entry->resource_id());
1000
1001 const FilePath kFilePath2 = FilePath(
1002 FILE_PATH_LITERAL("drive/Duplicate Name (2).txt"));
1003 entry = GetEntryInfoByPathSync(kFilePath2);
1004 ASSERT_TRUE(entry.get());
1005 EXPECT_EQ("file:4_file_resource_id", entry->resource_id());
1006 }
1007
1008 TEST_F(GDataFileSystemTest, SearchExistingDirectory) {
1009 LoadRootFeedDocument("root_feed.json");
1010
1011 const FilePath kFilePath = FilePath(
1012 FILE_PATH_LITERAL("drive/Directory 1"));
1013 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
1014 ASSERT_TRUE(entry.get());
1015 ASSERT_EQ("folder:1_folder_resource_id", entry->resource_id());
1016 }
1017
1018 TEST_F(GDataFileSystemTest, SearchInSubdir) {
1019 LoadRootFeedDocument("root_feed.json");
1020
1021 const FilePath kFilePath = FilePath(
1022 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1023 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
1024 ASSERT_TRUE(entry.get());
1025 ASSERT_EQ("file:subdirectory_file_1_id", entry->resource_id());
1026 }
1027
1028 // Check the reconstruction of the directory structure from only the root feed.
1029 TEST_F(GDataFileSystemTest, SearchInSubSubdir) {
1030 LoadRootFeedDocument("root_feed.json");
1031
1032 const FilePath kFilePath = FilePath(
1033 FILE_PATH_LITERAL("drive/Directory 1/Sub Directory Folder/"
1034 "Sub Sub Directory Folder"));
1035 scoped_ptr<DriveEntryProto> entry = GetEntryInfoByPathSync(kFilePath);
1036 ASSERT_TRUE(entry.get());
1037 ASSERT_EQ("folder:sub_sub_directory_folder_id", entry->resource_id());
1038 }
1039
1040 TEST_F(GDataFileSystemTest, FilePathTests) {
1041 LoadRootFeedDocument("root_feed.json");
1042
1043 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/File 1.txt"))));
1044 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))));
1045 EXPECT_TRUE(EntryExists(
1046 FilePath(
1047 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"))));
1048 }
1049
1050 TEST_F(GDataFileSystemTest, ChangeFeed_AddAndDeleteFileInRoot) {
1051 int latest_changelog = 0;
1052 LoadRootFeedDocument("root_feed.json");
1053
1054 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1055 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(2);
1056
1057 LoadChangeFeed("delta_file_added_in_root.json", ++latest_changelog);
1058 EXPECT_TRUE(
1059 EntryExists(FilePath(FILE_PATH_LITERAL("drive/Added file.gdoc"))));
1060
1061 LoadChangeFeed("delta_file_deleted_in_root.json", ++latest_changelog);
1062 EXPECT_FALSE(
1063 EntryExists(FilePath(FILE_PATH_LITERAL("drive/Added file.gdoc"))));
1064 }
1065
1066
1067 TEST_F(GDataFileSystemTest, ChangeFeed_AddAndDeleteFileFromExistingDirectory) {
1068 int latest_changelog = 0;
1069 LoadRootFeedDocument("root_feed.json");
1070
1071 EXPECT_TRUE(EntryExists(FilePath(
1072 FILE_PATH_LITERAL("drive/Directory 1"))));
1073
1074 // Add file to an existing directory.
1075 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1076 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1077 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1078 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1079 LoadChangeFeed("delta_file_added_in_directory.json", ++latest_changelog);
1080 EXPECT_TRUE(EntryExists(FilePath(
1081 FILE_PATH_LITERAL("drive/Directory 1/Added file.gdoc"))));
1082
1083 // Remove that file from the directory.
1084 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1085 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1086 LoadChangeFeed("delta_file_deleted_in_directory.json", ++latest_changelog);
1087 EXPECT_TRUE(EntryExists(FilePath(
1088 FILE_PATH_LITERAL("drive/Directory 1"))));
1089 EXPECT_FALSE(EntryExists(FilePath(
1090 FILE_PATH_LITERAL("drive/Directory 1/Added file.gdoc"))));
1091 }
1092
1093 TEST_F(GDataFileSystemTest, ChangeFeed_AddFileToNewDirectory) {
1094 int latest_changelog = 0;
1095 LoadRootFeedDocument("root_feed.json");
1096 // Add file to a new directory.
1097 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1098 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1099 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1100 Eq(FilePath(FILE_PATH_LITERAL("drive/New Directory"))))).Times(1);
1101
1102 LoadChangeFeed("delta_file_added_in_new_directory.json", ++latest_changelog);
1103
1104 EXPECT_TRUE(EntryExists(FilePath(
1105 FILE_PATH_LITERAL("drive/New Directory"))));
1106 EXPECT_TRUE(EntryExists(FilePath(
1107 FILE_PATH_LITERAL("drive/New Directory/File in new dir.gdoc"))));
1108 }
1109
1110 TEST_F(GDataFileSystemTest, ChangeFeed_AddFileToNewButDeletedDirectory) {
1111 int latest_changelog = 0;
1112 LoadRootFeedDocument("root_feed.json");
1113
1114 // This feed contains thw following updates:
1115 // 1) A new PDF file is added to a new directory
1116 // 2) but the new directory is marked "deleted" (i.e. moved to Trash)
1117 // Hence, the PDF file should be just ignored.
1118 LoadChangeFeed("delta_file_added_in_new_but_deleted_directory.json",
1119 ++latest_changelog);
1120 }
1121
1122 TEST_F(GDataFileSystemTest, ChangeFeed_DirectoryMovedFromRootToDirectory) {
1123 int latest_changelog = 0;
1124 LoadRootFeedDocument("root_feed.json");
1125
1126 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1127 "drive/Directory 2"))));
1128 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1129 "drive/Directory 1"))));
1130 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1131 "drive/Directory 1/SubDirectory File 1.txt"))));
1132 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1133 "drive/Directory 1/Sub Directory Folder"))));
1134 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1135 "drive/Directory 1/Sub Directory Folder/Sub Sub Directory Folder"))));
1136
1137 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1138 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1139 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1140 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 2"))))).Times(1);
1141 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1142 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 2/Directory 1")))))
1143 .Times(1);
1144 LoadChangeFeed("delta_dir_moved_from_root_to_directory.json",
1145 ++latest_changelog);
1146
1147 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1148 "drive/Directory 2"))));
1149 EXPECT_FALSE(EntryExists(FilePath(FILE_PATH_LITERAL(
1150 "drive/Directory 1"))));
1151 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1152 "drive/Directory 2/Directory 1"))));
1153 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1154 "drive/Directory 2/Directory 1/SubDirectory File 1.txt"))));
1155 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1156 "drive/Directory 2/Directory 1/Sub Directory Folder"))));
1157 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1158 "drive/Directory 2/Directory 1/Sub Directory Folder/"
1159 "Sub Sub Directory Folder"))));
1160 }
1161
1162 TEST_F(GDataFileSystemTest, ChangeFeed_FileMovedFromDirectoryToRoot) {
1163 int latest_changelog = 0;
1164 LoadRootFeedDocument("root_feed.json");
1165
1166 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1167 "drive/Directory 1"))));
1168 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1169 "drive/Directory 1/Sub Directory Folder"))));
1170 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1171 "drive/Directory 1/Sub Directory Folder/Sub Sub Directory Folder"))));
1172 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1173 "drive/Directory 1/SubDirectory File 1.txt"))));
1174
1175 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1176 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1177 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1178 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1179 LoadChangeFeed("delta_file_moved_from_directory_to_root.json",
1180 ++latest_changelog);
1181
1182 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1183 "drive/Directory 1"))));
1184 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1185 "drive/Directory 1/Sub Directory Folder"))));
1186 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1187 "drive/Directory 1/Sub Directory Folder/Sub Sub Directory Folder"))));
1188 EXPECT_FALSE(EntryExists(FilePath(FILE_PATH_LITERAL(
1189 "drive/Directory 1/SubDirectory File 1.txt"))));
1190 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1191 "drive/SubDirectory File 1.txt"))));
1192 }
1193
1194 TEST_F(GDataFileSystemTest, ChangeFeed_FileRenamedInDirectory) {
1195 int latest_changelog = 0;
1196 LoadRootFeedDocument("root_feed.json");
1197
1198 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1199 "drive/Directory 1"))));
1200 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1201 "drive/Directory 1/SubDirectory File 1.txt"))));
1202
1203 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1204 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1205 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1206 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1207 LoadChangeFeed("delta_file_renamed_in_directory.json",
1208 ++latest_changelog);
1209
1210 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1211 "drive/Directory 1"))));
1212 EXPECT_FALSE(EntryExists(FilePath(FILE_PATH_LITERAL(
1213 "drive/Directory 1/SubDirectory File 1.txt"))));
1214 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL(
1215 "drive/Directory 1/New SubDirectory File 1.txt"))));
1216 }
1217
1218 TEST_F(GDataFileSystemTest, CachedFeedLoading) {
1219 SaveTestFileSystem();
1220 TestLoadMetadataFromCache();
1221
1222 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/File1"))));
1223 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Dir1"))));
1224 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Dir1/File2"))));
1225 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/Dir1/SubDir2"))));
1226 EXPECT_TRUE(EntryExists(
1227 FilePath(FILE_PATH_LITERAL("drive/Dir1/SubDir2/File3"))));
1228 }
1229
1230 TEST_F(GDataFileSystemTest, CachedFeadLoadingThenServerFeedLoading) {
1231 SaveTestFileSystem();
1232
1233 // SaveTestFileSystem and "account_metadata.json" have the same changestamp,
1234 // so no request for new feeds (i.e., call to GetDocuments) should happen.
1235 mock_drive_service_->set_account_metadata(
1236 LoadJSONFile("account_metadata.json"));
1237 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
1238 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
1239 EXPECT_CALL(*mock_drive_service_, GetDocuments(_, _, _, _, _)).Times(0);
1240
1241 // Kicks loading of cached file system and query for server update.
1242 EXPECT_TRUE(EntryExists(FilePath(FILE_PATH_LITERAL("drive/File1"))));
1243
1244 // Since the file system has verified that it holds the latest snapshot,
1245 // it should change its state to FROM_SERVER, which admits periodic refresh.
1246 // To test it, call CheckForUpdates and verify it does try to check updates.
1247 mock_drive_service_->set_account_metadata(
1248 LoadJSONFile("account_metadata.json"));
1249 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
1250 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
1251
1252 file_system_->CheckForUpdates();
1253 test_util::RunBlockingPoolTask();
1254 }
1255
1256 TEST_F(GDataFileSystemTest, TransferFileFromLocalToRemote_RegularFile) {
1257 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
1258 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
1259
1260 LoadRootFeedDocument("root_feed.json");
1261
1262 // We'll add a file to the Drive root directory.
1263 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1264 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1265
1266 FileOperationCallback callback =
1267 base::Bind(&CallbackHelper::FileOperationCallback,
1268 callback_helper_.get());
1269
1270 // Prepare a local file.
1271 ScopedTempDir temp_dir;
1272 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1273 const FilePath local_src_file_path = temp_dir.path().Append("local.txt");
1274 const std::string kContent = "hello";
1275 file_util::WriteFile(local_src_file_path, kContent.data(), kContent.size());
1276
1277 // Confirm that the remote file does not exist.
1278 const FilePath remote_dest_file_path(FILE_PATH_LITERAL("drive/remote.txt"));
1279 EXPECT_FALSE(EntryExists(remote_dest_file_path));
1280
1281 // Transfer the local file to Drive.
1282 file_system_->TransferFileFromLocalToRemote(
1283 local_src_file_path, remote_dest_file_path, callback);
1284 test_util::RunBlockingPoolTask();
1285
1286 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1287
1288 // Now the remote file should exist.
1289 EXPECT_TRUE(EntryExists(remote_dest_file_path));
1290 }
1291
1292 TEST_F(GDataFileSystemTest, TransferFileFromLocalToRemote_HostedDocument) {
1293 LoadRootFeedDocument("root_feed.json");
1294
1295 // Prepare a local file, which is a json file of a hosted document, which
1296 // matches "Document 1" in root_feed.json.
1297 ScopedTempDir temp_dir;
1298 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1299 const FilePath local_src_file_path = temp_dir.path().Append("local.gdoc");
1300 const std::string kEditUrl =
1301 "https://3_document_self_link/document:5_document_resource_id";
1302 const std::string kResourceId = "document:5_document_resource_id";
1303 const std::string kContent =
1304 base::StringPrintf("{\"url\": \"%s\", \"resource_id\": \"%s\"}",
1305 kEditUrl.c_str(), kResourceId.c_str());
1306 file_util::WriteFile(local_src_file_path, kContent.data(), kContent.size());
1307
1308 // Confirm that the remote file does not exist.
1309 const FilePath remote_dest_file_path(
1310 FILE_PATH_LITERAL("drive/Directory 1/Document 1.gdoc"));
1311 EXPECT_FALSE(EntryExists(remote_dest_file_path));
1312
1313 // We'll add a file to "Directory 1" directory on Drive.
1314 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1315 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1316
1317 // We'll copy a hosted document using CopyDocument.
1318 // ".gdoc" suffix should be stripped when copying.
1319 scoped_ptr<base::Value> document(LoadJSONFile("uploaded_document.json"));
1320 EXPECT_CALL(*mock_drive_service_,
1321 CopyDocument(kResourceId,
1322 FILE_PATH_LITERAL("Document 1"),
1323 _))
1324 .WillOnce(MockCopyDocument(gdata::HTTP_SUCCESS, &document));
1325 // We'll then add the hosted document to the destination directory.
1326 EXPECT_CALL(*mock_drive_service_,
1327 AddResourceToDirectory(_, _, _)).Times(1);
1328
1329 FileOperationCallback callback =
1330 base::Bind(&CallbackHelper::FileOperationCallback,
1331 callback_helper_.get());
1332
1333 // Transfer the local file to Drive.
1334 file_system_->TransferFileFromLocalToRemote(
1335 local_src_file_path, remote_dest_file_path, callback);
1336 test_util::RunBlockingPoolTask();
1337
1338 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1339
1340 // Now the remote file should exist.
1341 EXPECT_TRUE(EntryExists(remote_dest_file_path));
1342 }
1343
1344 TEST_F(GDataFileSystemTest, TransferFileFromRemoteToLocal_RegularFile) {
1345 LoadRootFeedDocument("root_feed.json");
1346
1347 FileOperationCallback callback =
1348 base::Bind(&CallbackHelper::FileOperationCallback,
1349 callback_helper_.get());
1350
1351 ScopedTempDir temp_dir;
1352 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1353 FilePath local_dest_file_path = temp_dir.path().Append("local_copy.txt");
1354
1355 FilePath remote_src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1356 scoped_ptr<DriveEntryProto> file = GetEntryInfoByPathSync(
1357 remote_src_file_path);
1358 FilePath cache_file = GetCachePathForFile(
1359 file->resource_id(),
1360 file->file_specific_info().file_md5());
1361 const int64 file_size = file->file_info().size();
1362
1363 // Pretend we have enough space.
1364 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
1365 .Times(2).WillRepeatedly(Return(file_size + kMinFreeSpace));
1366
1367 const std::string remote_src_file_data = "Test file data";
1368 mock_drive_service_->set_file_data(new std::string(remote_src_file_data));
1369
1370 // Before Download starts metadata from server will be fetched.
1371 // We will read content url from the result.
1372 scoped_ptr<base::Value> document(LoadJSONFile("document_to_download.json"));
1373 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
1374
1375 // The file is obtained with the mock DriveService.
1376 EXPECT_CALL(*mock_drive_service_,
1377 DownloadFile(remote_src_file_path,
1378 cache_file,
1379 GURL("https://file_content_url_changed/"),
1380 _, _))
1381 .Times(1);
1382
1383 file_system_->TransferFileFromRemoteToLocal(
1384 remote_src_file_path, local_dest_file_path, callback);
1385 test_util::RunBlockingPoolTask();
1386
1387 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1388
1389 std::string cache_file_data;
1390 EXPECT_TRUE(file_util::ReadFileToString(cache_file, &cache_file_data));
1391 EXPECT_EQ(remote_src_file_data, cache_file_data);
1392
1393 std::string local_dest_file_data;
1394 EXPECT_TRUE(file_util::ReadFileToString(local_dest_file_path,
1395 &local_dest_file_data));
1396 EXPECT_EQ(remote_src_file_data, local_dest_file_data);
1397 }
1398
1399 TEST_F(GDataFileSystemTest, TransferFileFromRemoteToLocal_HostedDocument) {
1400 LoadRootFeedDocument("root_feed.json");
1401
1402 FileOperationCallback callback =
1403 base::Bind(&CallbackHelper::FileOperationCallback,
1404 callback_helper_.get());
1405
1406 ScopedTempDir temp_dir;
1407 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1408 FilePath local_dest_file_path = temp_dir.path().Append("local_copy.txt");
1409 FilePath remote_src_file_path(FILE_PATH_LITERAL("drive/Document 1.gdoc"));
1410 file_system_->TransferFileFromRemoteToLocal(
1411 remote_src_file_path, local_dest_file_path, callback);
1412 test_util::RunBlockingPoolTask();
1413
1414 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1415
1416 scoped_ptr<DriveEntryProto> entry_proto = GetEntryInfoByPathSync(
1417 remote_src_file_path);
1418 ASSERT_TRUE(entry_proto.get());
1419 VerifyHostedDocumentJSONFile(*entry_proto, local_dest_file_path);
1420 }
1421
1422 TEST_F(GDataFileSystemTest, CopyNotExistingFile) {
1423 FilePath src_file_path(FILE_PATH_LITERAL("drive/Dummy file.txt"));
1424 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1425
1426 LoadRootFeedDocument("root_feed.json");
1427
1428 EXPECT_FALSE(EntryExists(src_file_path));
1429
1430 FileOperationCallback callback =
1431 base::Bind(&CallbackHelper::FileOperationCallback,
1432 callback_helper_.get());
1433
1434 file_system_->Copy(src_file_path, dest_file_path, callback);
1435 test_util::RunBlockingPoolTask();
1436 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1437
1438 EXPECT_FALSE(EntryExists(src_file_path));
1439 EXPECT_FALSE(EntryExists(dest_file_path));
1440 }
1441
1442 TEST_F(GDataFileSystemTest, CopyFileToNonExistingDirectory) {
1443 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1444 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Dummy"));
1445 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Dummy/Test.log"));
1446
1447 LoadRootFeedDocument("root_feed.json");
1448
1449 ASSERT_TRUE(EntryExists(src_file_path));
1450 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1451 src_file_path);
1452 ASSERT_TRUE(src_entry_proto.get());
1453 std::string src_file_path_resource_id =
1454 src_entry_proto->resource_id();
1455 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1456
1457 EXPECT_FALSE(EntryExists(dest_parent_path));
1458
1459 FileOperationCallback callback =
1460 base::Bind(&CallbackHelper::FileOperationCallback,
1461 callback_helper_.get());
1462
1463 file_system_->Move(src_file_path, dest_file_path, callback);
1464 test_util::RunBlockingPoolTask();
1465 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1466
1467 EXPECT_TRUE(EntryExists(src_file_path));
1468 EXPECT_FALSE(EntryExists(dest_parent_path));
1469 EXPECT_FALSE(EntryExists(dest_file_path));
1470 }
1471
1472 // Test the case where the parent of |dest_file_path| is an existing file,
1473 // not a directory.
1474 TEST_F(GDataFileSystemTest, CopyFileToInvalidPath) {
1475 FilePath src_file_path(FILE_PATH_LITERAL("drive/Document 1.gdoc"));
1476 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Duplicate Name.txt"));
1477 FilePath dest_file_path(FILE_PATH_LITERAL(
1478 "drive/Duplicate Name.txt/Document 1.gdoc"));
1479
1480 LoadRootFeedDocument("root_feed.json");
1481
1482 ASSERT_TRUE(EntryExists(src_file_path));
1483 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1484 src_file_path);
1485 ASSERT_TRUE(src_entry_proto.get());
1486 std::string src_file_resource_id =
1487 src_entry_proto->resource_id();
1488 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1489
1490 ASSERT_TRUE(EntryExists(dest_parent_path));
1491 scoped_ptr<DriveEntryProto> dest_entry_proto = GetEntryInfoByPathSync(
1492 dest_parent_path);
1493 ASSERT_TRUE(dest_entry_proto.get());
1494
1495 FileOperationCallback callback =
1496 base::Bind(&CallbackHelper::FileOperationCallback,
1497 callback_helper_.get());
1498
1499 file_system_->Copy(src_file_path, dest_file_path, callback);
1500 test_util::RunBlockingPoolTask();
1501 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_A_DIRECTORY,
1502 callback_helper_->last_error_);
1503
1504 EXPECT_TRUE(EntryExists(src_file_path));
1505 EXPECT_TRUE(EntryExists(src_file_path));
1506 EXPECT_TRUE(EntryExists(dest_parent_path));
1507
1508 EXPECT_FALSE(EntryExists(dest_file_path));
1509 }
1510
1511 TEST_F(GDataFileSystemTest, RenameFile) {
1512 const FilePath src_file_path(
1513 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1514 const FilePath src_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1515 const FilePath dest_file_path(
1516 FILE_PATH_LITERAL("drive/Directory 1/Test.log"));
1517
1518 LoadRootFeedDocument("root_feed.json");
1519
1520 ASSERT_TRUE(EntryExists(src_file_path));
1521 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1522 src_file_path);
1523 ASSERT_TRUE(src_entry_proto.get());
1524 std::string src_file_resource_id =
1525 src_entry_proto->resource_id();
1526
1527 EXPECT_CALL(*mock_drive_service_,
1528 RenameResource(GURL(src_entry_proto->edit_url()),
1529 FILE_PATH_LITERAL("Test.log"), _));
1530
1531 FileOperationCallback callback =
1532 base::Bind(&CallbackHelper::FileOperationCallback,
1533 callback_helper_.get());
1534
1535 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1536 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1537
1538 file_system_->Move(src_file_path, dest_file_path, callback);
1539 test_util::RunBlockingPoolTask();
1540 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1541
1542 EXPECT_FALSE(EntryExists(src_file_path));
1543 EXPECT_TRUE(EntryExists(dest_file_path));
1544 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1545 }
1546
1547 TEST_F(GDataFileSystemTest, MoveFileFromRootToSubDirectory) {
1548 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1549 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1550 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Directory 1/Test.log"));
1551
1552 LoadRootFeedDocument("root_feed.json");
1553
1554 ASSERT_TRUE(EntryExists(src_file_path));
1555 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1556 src_file_path);
1557 ASSERT_TRUE(src_entry_proto.get());
1558 std::string src_file_resource_id =
1559 src_entry_proto->resource_id();
1560 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1561
1562 ASSERT_TRUE(EntryExists(dest_parent_path));
1563 scoped_ptr<DriveEntryProto> dest_parent_proto = GetEntryInfoByPathSync(
1564 dest_parent_path);
1565 ASSERT_TRUE(dest_parent_proto.get());
1566 ASSERT_TRUE(dest_parent_proto->file_info().is_directory());
1567 EXPECT_FALSE(dest_parent_proto->content_url().empty());
1568
1569 EXPECT_CALL(*mock_drive_service_,
1570 RenameResource(GURL(src_entry_proto->edit_url()),
1571 FILE_PATH_LITERAL("Test.log"), _));
1572 EXPECT_CALL(*mock_drive_service_,
1573 AddResourceToDirectory(
1574 GURL(dest_parent_proto->content_url()),
1575 GURL(src_entry_proto->edit_url()), _));
1576
1577 FileOperationCallback callback =
1578 base::Bind(&CallbackHelper::FileOperationCallback,
1579 callback_helper_.get());
1580
1581 // Expect notification for both source and destination directories.
1582 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1583 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1584 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1585 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1586
1587 file_system_->Move(src_file_path, dest_file_path, callback);
1588 test_util::RunBlockingPoolTask();
1589 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1590
1591 EXPECT_FALSE(EntryExists(src_file_path));
1592 EXPECT_TRUE(EntryExists(dest_file_path));
1593 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1594 }
1595
1596 TEST_F(GDataFileSystemTest, MoveFileFromSubDirectoryToRoot) {
1597 FilePath src_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1598 FilePath src_file_path(
1599 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1600 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1601
1602 LoadRootFeedDocument("root_feed.json");
1603
1604 ASSERT_TRUE(EntryExists(src_file_path));
1605 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1606 src_file_path);
1607 ASSERT_TRUE(src_entry_proto.get());
1608 std::string src_file_resource_id =
1609 src_entry_proto->resource_id();
1610 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1611
1612 ASSERT_TRUE(EntryExists(src_parent_path));
1613 scoped_ptr<DriveEntryProto> src_parent_proto = GetEntryInfoByPathSync(
1614 src_parent_path);
1615 ASSERT_TRUE(src_parent_proto.get());
1616 ASSERT_TRUE(src_parent_proto->file_info().is_directory());
1617 EXPECT_FALSE(src_parent_proto->content_url().empty());
1618
1619 EXPECT_CALL(*mock_drive_service_,
1620 RenameResource(GURL(src_entry_proto->edit_url()),
1621 FILE_PATH_LITERAL("Test.log"), _));
1622 EXPECT_CALL(*mock_drive_service_,
1623 RemoveResourceFromDirectory(
1624 GURL(src_parent_proto->content_url()),
1625 GURL(src_entry_proto->edit_url()),
1626 src_file_resource_id, _));
1627
1628 FileOperationCallback callback =
1629 base::Bind(&CallbackHelper::FileOperationCallback,
1630 callback_helper_.get());
1631
1632 // Expect notification for both source and destination directories.
1633 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1634 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1635 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1636 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1637
1638 file_system_->Move(src_file_path, dest_file_path, callback);
1639 test_util::RunBlockingPoolTask();
1640 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1641
1642 EXPECT_FALSE(EntryExists(src_file_path));
1643 ASSERT_TRUE(EntryExists(dest_file_path));
1644 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1645 }
1646
1647 TEST_F(GDataFileSystemTest, MoveFileBetweenSubDirectories) {
1648 FilePath src_parent_path(FILE_PATH_LITERAL("drive/Directory 1"));
1649 FilePath src_file_path(
1650 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1651 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/New Folder 1"));
1652 FilePath dest_file_path(FILE_PATH_LITERAL("drive/New Folder 1/Test.log"));
1653 FilePath interim_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1654
1655 LoadRootFeedDocument("root_feed.json");
1656
1657 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1658 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1659
1660 AddDirectoryFromFile(dest_parent_path, "directory_entry_atom.json");
1661
1662 ASSERT_TRUE(EntryExists(src_file_path));
1663 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1664 src_file_path);
1665 ASSERT_TRUE(src_entry_proto.get());
1666 std::string src_file_resource_id =
1667 src_entry_proto->resource_id();
1668 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1669
1670 ASSERT_TRUE(EntryExists(src_parent_path));
1671 scoped_ptr<DriveEntryProto> src_parent_proto = GetEntryInfoByPathSync(
1672 src_parent_path);
1673 ASSERT_TRUE(src_parent_proto.get());
1674 ASSERT_TRUE(src_parent_proto->file_info().is_directory());
1675 EXPECT_FALSE(src_parent_proto->content_url().empty());
1676
1677 ASSERT_TRUE(EntryExists(dest_parent_path));
1678 scoped_ptr<DriveEntryProto> dest_parent_proto = GetEntryInfoByPathSync(
1679 dest_parent_path);
1680 ASSERT_TRUE(dest_parent_proto.get());
1681 ASSERT_TRUE(dest_parent_proto->file_info().is_directory());
1682 EXPECT_FALSE(dest_parent_proto->content_url().empty());
1683
1684 EXPECT_FALSE(EntryExists(interim_file_path));
1685
1686 EXPECT_CALL(*mock_drive_service_,
1687 RenameResource(GURL(src_entry_proto->edit_url()),
1688 FILE_PATH_LITERAL("Test.log"), _));
1689 EXPECT_CALL(*mock_drive_service_,
1690 RemoveResourceFromDirectory(
1691 GURL(src_parent_proto->content_url()),
1692 GURL(src_entry_proto->edit_url()),
1693 src_file_resource_id, _));
1694 EXPECT_CALL(*mock_drive_service_,
1695 AddResourceToDirectory(
1696 GURL(dest_parent_proto->content_url()),
1697 GURL(src_entry_proto->edit_url()),
1698 _));
1699
1700 FileOperationCallback callback =
1701 base::Bind(&CallbackHelper::FileOperationCallback,
1702 callback_helper_.get());
1703
1704 // Expect notification for both source and destination directories plus
1705 // interim file path.
1706 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1707 Eq(FilePath(FILE_PATH_LITERAL("drive/Directory 1"))))).Times(1);
1708 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1709 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1710 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1711 Eq(FilePath(FILE_PATH_LITERAL("drive/New Folder 1"))))).Times(1);
1712
1713 file_system_->Move(src_file_path, dest_file_path, callback);
1714 test_util::RunBlockingPoolTask();
1715 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1716
1717 EXPECT_FALSE(EntryExists(src_file_path));
1718 EXPECT_FALSE(EntryExists(interim_file_path));
1719
1720 EXPECT_FALSE(EntryExists(src_file_path));
1721 EXPECT_TRUE(EntryExists(dest_file_path));
1722 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path));
1723 }
1724
1725 TEST_F(GDataFileSystemTest, MoveNotExistingFile) {
1726 FilePath src_file_path(FILE_PATH_LITERAL("drive/Dummy file.txt"));
1727 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Test.log"));
1728
1729 LoadRootFeedDocument("root_feed.json");
1730
1731 EXPECT_FALSE(EntryExists(src_file_path));
1732
1733 FileOperationCallback callback =
1734 base::Bind(&CallbackHelper::FileOperationCallback,
1735 callback_helper_.get());
1736
1737 file_system_->Move(src_file_path, dest_file_path, callback);
1738 test_util::RunBlockingPoolTask();
1739 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1740
1741 EXPECT_FALSE(EntryExists(src_file_path));
1742 EXPECT_FALSE(EntryExists(dest_file_path));
1743 }
1744
1745 TEST_F(GDataFileSystemTest, MoveFileToNonExistingDirectory) {
1746 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1747 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Dummy"));
1748 FilePath dest_file_path(FILE_PATH_LITERAL("drive/Dummy/Test.log"));
1749
1750 LoadRootFeedDocument("root_feed.json");
1751
1752 ASSERT_TRUE(EntryExists(src_file_path));
1753 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1754 src_file_path);
1755 ASSERT_TRUE(src_entry_proto.get());
1756 std::string src_file_resource_id =
1757 src_entry_proto->resource_id();
1758 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1759
1760 EXPECT_FALSE(EntryExists(dest_parent_path));
1761
1762 FileOperationCallback callback =
1763 base::Bind(&CallbackHelper::FileOperationCallback,
1764 callback_helper_.get());
1765
1766 file_system_->Move(src_file_path, dest_file_path, callback);
1767 test_util::RunBlockingPoolTask();
1768 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
1769
1770
1771 EXPECT_FALSE(EntryExists(dest_parent_path));
1772 EXPECT_FALSE(EntryExists(dest_file_path));
1773 }
1774
1775 // Test the case where the parent of |dest_file_path| is a existing file,
1776 // not a directory.
1777 TEST_F(GDataFileSystemTest, MoveFileToInvalidPath) {
1778 FilePath src_file_path(FILE_PATH_LITERAL("drive/File 1.txt"));
1779 FilePath dest_parent_path(FILE_PATH_LITERAL("drive/Duplicate Name.txt"));
1780 FilePath dest_file_path(FILE_PATH_LITERAL(
1781 "drive/Duplicate Name.txt/Test.log"));
1782
1783 LoadRootFeedDocument("root_feed.json");
1784
1785 ASSERT_TRUE(EntryExists(src_file_path));
1786 scoped_ptr<DriveEntryProto> src_entry_proto = GetEntryInfoByPathSync(
1787 src_file_path);
1788 ASSERT_TRUE(src_entry_proto.get());
1789 std::string src_file_resource_id =
1790 src_entry_proto->resource_id();
1791 EXPECT_FALSE(src_entry_proto->edit_url().empty());
1792
1793 ASSERT_TRUE(EntryExists(dest_parent_path));
1794 scoped_ptr<DriveEntryProto> dest_parent_proto = GetEntryInfoByPathSync(
1795 dest_parent_path);
1796 ASSERT_TRUE(dest_parent_proto.get());
1797
1798 FileOperationCallback callback =
1799 base::Bind(&CallbackHelper::FileOperationCallback,
1800 callback_helper_.get());
1801
1802 file_system_->Move(src_file_path, dest_file_path, callback);
1803 test_util::RunBlockingPoolTask();
1804 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_A_DIRECTORY,
1805 callback_helper_->last_error_);
1806
1807 EXPECT_TRUE(EntryExists(src_file_path));
1808 EXPECT_TRUE(EntryExists(dest_parent_path));
1809 EXPECT_FALSE(EntryExists(dest_file_path));
1810 }
1811
1812 TEST_F(GDataFileSystemTest, RemoveEntries) {
1813 LoadRootFeedDocument("root_feed.json");
1814
1815 FilePath nonexisting_file(FILE_PATH_LITERAL("drive/Dummy file.txt"));
1816 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
1817 FilePath dir_in_root(FILE_PATH_LITERAL("drive/Directory 1"));
1818 FilePath file_in_subdir(
1819 FILE_PATH_LITERAL("drive/Directory 1/SubDirectory File 1.txt"));
1820
1821 ASSERT_TRUE(EntryExists(file_in_root));
1822 scoped_ptr<DriveEntryProto> file_in_root_proto = GetEntryInfoByPathSync(
1823 file_in_root);
1824 ASSERT_TRUE(file_in_root_proto.get());
1825
1826 ASSERT_TRUE(EntryExists(dir_in_root));
1827 scoped_ptr<DriveEntryProto> dir_in_root_proto = GetEntryInfoByPathSync(
1828 dir_in_root);
1829 ASSERT_TRUE(dir_in_root_proto.get());
1830 ASSERT_TRUE(dir_in_root_proto->file_info().is_directory());
1831
1832 ASSERT_TRUE(EntryExists(file_in_subdir));
1833 scoped_ptr<DriveEntryProto> file_in_subdir_proto = GetEntryInfoByPathSync(
1834 file_in_subdir);
1835 ASSERT_TRUE(file_in_subdir_proto.get());
1836
1837 // Once for file in root and once for file...
1838 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1839 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(2);
1840
1841 // Remove first file in root.
1842 EXPECT_TRUE(RemoveEntry(file_in_root));
1843 EXPECT_FALSE(EntryExists(file_in_root));
1844 EXPECT_TRUE(EntryExists(dir_in_root));
1845 EXPECT_TRUE(EntryExists(file_in_subdir));
1846
1847 // Remove directory.
1848 EXPECT_TRUE(RemoveEntry(dir_in_root));
1849 EXPECT_FALSE(EntryExists(file_in_root));
1850 EXPECT_FALSE(EntryExists(dir_in_root));
1851 EXPECT_FALSE(EntryExists(file_in_subdir));
1852
1853 // Try removing file in already removed subdirectory.
1854 EXPECT_FALSE(RemoveEntry(file_in_subdir));
1855
1856 // Try removing non-existing file.
1857 EXPECT_FALSE(RemoveEntry(nonexisting_file));
1858
1859 // Try removing root file element.
1860 EXPECT_FALSE(RemoveEntry(FilePath(FILE_PATH_LITERAL("drive"))));
1861
1862 // Need this to ensure OnDirectoryChanged() is run.
1863 test_util::RunBlockingPoolTask();
1864 }
1865
1866 TEST_F(GDataFileSystemTest, CreateDirectory) {
1867 LoadRootFeedDocument("root_feed.json");
1868
1869 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1870 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1871
1872 // Create directory in root.
1873 FilePath dir_path(FILE_PATH_LITERAL("drive/New Folder 1"));
1874 EXPECT_FALSE(EntryExists(dir_path));
1875 AddDirectoryFromFile(dir_path, "directory_entry_atom.json");
1876 EXPECT_TRUE(EntryExists(dir_path));
1877
1878 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1879 Eq(FilePath(FILE_PATH_LITERAL("drive/New Folder 1"))))).Times(1);
1880
1881 // Create directory in a sub directory.
1882 FilePath subdir_path(FILE_PATH_LITERAL("drive/New Folder 1/New Folder 2"));
1883 EXPECT_FALSE(EntryExists(subdir_path));
1884 AddDirectoryFromFile(subdir_path, "directory_entry_atom2.json");
1885 EXPECT_TRUE(EntryExists(subdir_path));
1886 }
1887
1888 TEST_F(GDataFileSystemTest, FindFirstMissingParentDirectory) {
1889 LoadRootFeedDocument("root_feed.json");
1890
1891 GURL last_dir_content_url;
1892 FilePath first_missing_parent_path;
1893
1894 // Create directory in root.
1895 FilePath dir_path(FILE_PATH_LITERAL("drive/New Folder 1"));
1896 EXPECT_EQ(
1897 GDataFileSystem::FOUND_MISSING,
1898 file_system_->FindFirstMissingParentDirectory(dir_path,
1899 &last_dir_content_url,
1900 &first_missing_parent_path));
1901 EXPECT_EQ(FilePath(FILE_PATH_LITERAL("drive/New Folder 1")),
1902 first_missing_parent_path);
1903 EXPECT_TRUE(last_dir_content_url.is_empty()); // root directory.
1904
1905 // Missing folders in subdir of an existing folder.
1906 FilePath dir_path2(FILE_PATH_LITERAL("drive/Directory 1/New Folder 2"));
1907 EXPECT_EQ(
1908 GDataFileSystem::FOUND_MISSING,
1909 file_system_->FindFirstMissingParentDirectory(dir_path2,
1910 &last_dir_content_url,
1911 &first_missing_parent_path));
1912 EXPECT_EQ(FilePath(FILE_PATH_LITERAL("drive/Directory 1/New Folder 2")),
1913 first_missing_parent_path);
1914 EXPECT_FALSE(last_dir_content_url.is_empty()); // non-root directory.
1915
1916 // Missing two folders on the path.
1917 FilePath dir_path3 = dir_path2.Append(FILE_PATH_LITERAL("Another Folder"));
1918 EXPECT_EQ(
1919 GDataFileSystem::FOUND_MISSING,
1920 file_system_->FindFirstMissingParentDirectory(dir_path3,
1921 &last_dir_content_url,
1922 &first_missing_parent_path));
1923 EXPECT_EQ(FilePath(FILE_PATH_LITERAL("drive/Directory 1/New Folder 2")),
1924 first_missing_parent_path);
1925 EXPECT_FALSE(last_dir_content_url.is_empty()); // non-root directory.
1926
1927 // Folders on top of an existing file.
1928 EXPECT_EQ(
1929 GDataFileSystem::FOUND_INVALID,
1930 file_system_->FindFirstMissingParentDirectory(
1931 FilePath(FILE_PATH_LITERAL("drive/File 1.txt/BadDir")),
1932 &last_dir_content_url,
1933 &first_missing_parent_path));
1934
1935 // Existing folder.
1936 EXPECT_EQ(
1937 GDataFileSystem::DIRECTORY_ALREADY_PRESENT,
1938 file_system_->FindFirstMissingParentDirectory(
1939 FilePath(FILE_PATH_LITERAL("drive/Directory 1")),
1940 &last_dir_content_url,
1941 &first_missing_parent_path));
1942 }
1943
1944 // Create a directory through the document service
1945 TEST_F(GDataFileSystemTest, CreateDirectoryWithService) {
1946 LoadRootFeedDocument("root_feed.json");
1947 EXPECT_CALL(*mock_drive_service_,
1948 CreateDirectory(_, "Sample Directory Title", _)).Times(1);
1949 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(
1950 Eq(FilePath(FILE_PATH_LITERAL("drive"))))).Times(1);
1951
1952 // Set last error so it's not a valid error code.
1953 callback_helper_->last_error_ = static_cast<DriveFileError>(1);
1954 file_system_->CreateDirectory(
1955 FilePath(FILE_PATH_LITERAL("drive/Sample Directory Title")),
1956 false, // is_exclusive
1957 true, // is_recursive
1958 base::Bind(&CallbackHelper::FileOperationCallback,
1959 callback_helper_.get()));
1960 test_util::RunBlockingPoolTask();
1961 // TODO(gspencer): Uncomment this when we get a blob that
1962 // works that can be returned from the mock.
1963 // EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
1964 }
1965
1966 TEST_F(GDataFileSystemTest, GetFileByPath_FromGData_EnoughSpace) {
1967 LoadRootFeedDocument("root_feed.json");
1968
1969 GetFileCallback callback =
1970 base::Bind(&CallbackHelper::GetFileCallback,
1971 callback_helper_.get());
1972
1973 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
1974 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
1975 FilePath downloaded_file = GetCachePathForFile(
1976 entry_proto->resource_id(),
1977 entry_proto->file_specific_info().file_md5());
1978 const int64 file_size = entry_proto->file_info().size();
1979
1980 // Pretend we have enough space.
1981 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
1982 .Times(2).WillRepeatedly(Return(file_size + kMinFreeSpace));
1983
1984 // Before Download starts metadata from server will be fetched.
1985 // We will read content url from the result.
1986 scoped_ptr<base::Value> document(LoadJSONFile("document_to_download.json"));
1987 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
1988
1989 // The file is obtained with the mock DriveService.
1990 EXPECT_CALL(*mock_drive_service_,
1991 DownloadFile(file_in_root,
1992 downloaded_file,
1993 GURL("https://file_content_url_changed/"),
1994 _, _))
1995 .Times(1);
1996
1997 file_system_->GetFileByPath(file_in_root, callback,
1998 GetContentCallback());
1999 test_util::RunBlockingPoolTask();
2000
2001 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2002 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2003 EXPECT_EQ(downloaded_file.value(),
2004 callback_helper_->download_path_.value());
2005 }
2006
2007 TEST_F(GDataFileSystemTest, GetFileByPath_FromGData_NoSpaceAtAll) {
2008 LoadRootFeedDocument("root_feed.json");
2009
2010 GetFileCallback callback =
2011 base::Bind(&CallbackHelper::GetFileCallback,
2012 callback_helper_.get());
2013
2014 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2015 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2016 FilePath downloaded_file = GetCachePathForFile(
2017 entry_proto->resource_id(),
2018 entry_proto->file_specific_info().file_md5());
2019
2020 // Pretend we have no space at all.
2021 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2022 .Times(2).WillRepeatedly(Return(0));
2023
2024 // Before Download starts metadata from server will be fetched.
2025 // We will read content url from the result.
2026 scoped_ptr<base::Value> document(LoadJSONFile("document_to_download.json"));
2027 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2028
2029 // The file is not obtained with the mock DriveService, because of no space.
2030 EXPECT_CALL(*mock_drive_service_,
2031 DownloadFile(file_in_root,
2032 downloaded_file,
2033 GURL("https://file_content_url_changed/"),
2034 _, _))
2035 .Times(0);
2036
2037 file_system_->GetFileByPath(file_in_root, callback,
2038 GetContentCallback());
2039 test_util::RunBlockingPoolTask();
2040
2041 EXPECT_EQ(DRIVE_FILE_ERROR_NO_SPACE,
2042 callback_helper_->last_error_);
2043 }
2044
2045 TEST_F(GDataFileSystemTest, GetFileByPath_FromGData_NoEnoughSpaceButCanFreeUp) {
2046 LoadRootFeedDocument("root_feed.json");
2047
2048 GetFileCallback callback =
2049 base::Bind(&CallbackHelper::GetFileCallback,
2050 callback_helper_.get());
2051
2052 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2053 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2054 FilePath downloaded_file = GetCachePathForFile(
2055 entry_proto->resource_id(),
2056 entry_proto->file_specific_info().file_md5());
2057 const int64 file_size = entry_proto->file_info().size();
2058
2059 // Pretend we have no space first (checked before downloading a file),
2060 // but then start reporting we have space. This is to emulate that
2061 // the disk space was freed up by removing temporary files.
2062 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2063 .WillOnce(Return(file_size + kMinFreeSpace))
2064 .WillOnce(Return(0))
2065 .WillOnce(Return(file_size + kMinFreeSpace))
2066 .WillOnce(Return(file_size + kMinFreeSpace));
2067
2068 // Store something in the temporary cache directory.
2069 TestStoreToCache("<resource_id>",
2070 "<md5>",
2071 GetTestFilePath("root_feed.json"),
2072 DRIVE_FILE_OK,
2073 test_util::TEST_CACHE_STATE_PRESENT,
2074 DriveCache::CACHE_TYPE_TMP);
2075 ASSERT_TRUE(CacheEntryExists("<resource_id>", "<md5>"));
2076 ASSERT_TRUE(CacheFileExists("<resource_id>", "<md5>"));
2077
2078 // Before Download starts metadata from server will be fetched.
2079 // We will read content url from the result.
2080 scoped_ptr<base::Value> document(LoadJSONFile("document_to_download.json"));
2081 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2082
2083 // The file is obtained with the mock DriveService, because of we freed up the
2084 // space.
2085 EXPECT_CALL(*mock_drive_service_,
2086 DownloadFile(file_in_root,
2087 downloaded_file,
2088 GURL("https://file_content_url_changed/"),
2089 _, _))
2090 .Times(1);
2091
2092 file_system_->GetFileByPath(file_in_root, callback,
2093 GetContentCallback());
2094 test_util::RunBlockingPoolTask();
2095
2096 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2097 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2098 EXPECT_EQ(downloaded_file.value(),
2099 callback_helper_->download_path_.value());
2100
2101 // The file should be removed in order to free up space, and the cache
2102 // entry should also be removed.
2103 ASSERT_FALSE(CacheEntryExists("<resource_id>", "<md5>"));
2104 ASSERT_FALSE(CacheFileExists("<resource_id>", "<md5>"));
2105 }
2106
2107 TEST_F(GDataFileSystemTest, GetFileByPath_FromGData_EnoughSpaceButBecomeFull) {
2108 LoadRootFeedDocument("root_feed.json");
2109
2110 GetFileCallback callback =
2111 base::Bind(&CallbackHelper::GetFileCallback,
2112 callback_helper_.get());
2113
2114 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2115 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2116 FilePath downloaded_file = GetCachePathForFile(
2117 entry_proto->resource_id(),
2118 entry_proto->file_specific_info().file_md5());
2119 const int64 file_size = entry_proto->file_info().size();
2120
2121 // Pretend we have enough space first (checked before downloading a file),
2122 // but then start reporting we have not enough space. This is to emulate that
2123 // the disk space becomes full after the file is downloaded for some reason
2124 // (ex. the actual file was larger than the expected size).
2125 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2126 .WillOnce(Return(file_size + kMinFreeSpace))
2127 .WillOnce(Return(kMinFreeSpace - 1))
2128 .WillOnce(Return(kMinFreeSpace - 1));
2129
2130 // Before Download starts metadata from server will be fetched.
2131 // We will read content url from the result.
2132 scoped_ptr<base::Value> document(LoadJSONFile("document_to_download.json"));
2133 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2134
2135 // The file is obtained with the mock DriveService.
2136 EXPECT_CALL(*mock_drive_service_,
2137 DownloadFile(file_in_root,
2138 downloaded_file,
2139 GURL("https://file_content_url_changed/"),
2140 _, _))
2141 .Times(1);
2142
2143 file_system_->GetFileByPath(file_in_root, callback,
2144 GetContentCallback());
2145 test_util::RunBlockingPoolTask();
2146
2147 EXPECT_EQ(DRIVE_FILE_ERROR_NO_SPACE,
2148 callback_helper_->last_error_);
2149 }
2150
2151 TEST_F(GDataFileSystemTest, GetFileByPath_FromCache) {
2152 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2153 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2154
2155 LoadRootFeedDocument("root_feed.json");
2156
2157 GetFileCallback callback =
2158 base::Bind(&CallbackHelper::GetFileCallback,
2159 callback_helper_.get());
2160
2161 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2162 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2163 FilePath downloaded_file = GetCachePathForFile(
2164 entry_proto->resource_id(),
2165 entry_proto->file_specific_info().file_md5());
2166
2167 // Store something as cached version of this file.
2168 TestStoreToCache(entry_proto->resource_id(),
2169 entry_proto->file_specific_info().file_md5(),
2170 GetTestFilePath("root_feed.json"),
2171 DRIVE_FILE_OK,
2172 test_util::TEST_CACHE_STATE_PRESENT,
2173 DriveCache::CACHE_TYPE_TMP);
2174
2175 // Make sure we don't fetch metadata for downloading file.
2176 EXPECT_CALL(*mock_drive_service_, GetDocumentEntry(_, _)).Times(0);
2177
2178 // Make sure we don't call downloads at all.
2179 EXPECT_CALL(*mock_drive_service_,
2180 DownloadFile(file_in_root,
2181 downloaded_file,
2182 GURL("https://file_content_url_changed/"),
2183 _, _))
2184 .Times(0);
2185
2186 file_system_->GetFileByPath(file_in_root, callback,
2187 GetContentCallback());
2188 test_util::RunBlockingPoolTask();
2189
2190 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2191 EXPECT_EQ(downloaded_file.value(),
2192 callback_helper_->download_path_.value());
2193 }
2194
2195 TEST_F(GDataFileSystemTest, GetFileByPath_HostedDocument) {
2196 LoadRootFeedDocument("root_feed.json");
2197
2198 GetFileCallback callback =
2199 base::Bind(&CallbackHelper::GetFileCallback,
2200 callback_helper_.get());
2201
2202 FilePath file_in_root(FILE_PATH_LITERAL("drive/Document 1.gdoc"));
2203 scoped_ptr<DriveEntryProto> src_entry_proto =
2204 GetEntryInfoByPathSync(file_in_root);
2205 ASSERT_TRUE(src_entry_proto.get());
2206
2207 file_system_->GetFileByPath(file_in_root, callback,
2208 GetContentCallback());
2209 test_util::RunBlockingPoolTask();
2210
2211 EXPECT_EQ(HOSTED_DOCUMENT, callback_helper_->file_type_);
2212 EXPECT_FALSE(callback_helper_->download_path_.empty());
2213
2214 ASSERT_TRUE(src_entry_proto.get());
2215 VerifyHostedDocumentJSONFile(*src_entry_proto,
2216 callback_helper_->download_path_);
2217 }
2218
2219 TEST_F(GDataFileSystemTest, GetFileByResourceId) {
2220 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2221 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2222
2223 LoadRootFeedDocument("root_feed.json");
2224
2225 GetFileCallback callback =
2226 base::Bind(&CallbackHelper::GetFileCallback,
2227 callback_helper_.get());
2228
2229 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2230 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2231 FilePath downloaded_file = GetCachePathForFile(
2232 entry_proto->resource_id(),
2233 entry_proto->file_specific_info().file_md5());
2234
2235 // Before Download starts metadata from server will be fetched.
2236 // We will read content url from the result.
2237 scoped_ptr<base::Value> document(LoadJSONFile("document_to_download.json"));
2238 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2239
2240 // The file is obtained with the mock DriveService, because it's not stored in
2241 // the cache.
2242 EXPECT_CALL(*mock_drive_service_,
2243 DownloadFile(file_in_root,
2244 downloaded_file,
2245 GURL("https://file_content_url_changed/"),
2246 _, _))
2247 .Times(1);
2248
2249 file_system_->GetFileByResourceId(entry_proto->resource_id(),
2250 callback,
2251 GetContentCallback());
2252 test_util::RunBlockingPoolTask();
2253
2254 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2255 EXPECT_EQ(downloaded_file.value(),
2256 callback_helper_->download_path_.value());
2257 }
2258
2259 TEST_F(GDataFileSystemTest, GetFileByResourceId_FromCache) {
2260 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2261 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2262
2263 LoadRootFeedDocument("root_feed.json");
2264
2265 GetFileCallback callback =
2266 base::Bind(&CallbackHelper::GetFileCallback,
2267 callback_helper_.get());
2268
2269 FilePath file_in_root(FILE_PATH_LITERAL("drive/File 1.txt"));
2270 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(file_in_root));
2271 FilePath downloaded_file = GetCachePathForFile(
2272 entry_proto->resource_id(),
2273 entry_proto->file_specific_info().file_md5());
2274
2275 // Store something as cached version of this file.
2276 TestStoreToCache(entry_proto->resource_id(),
2277 entry_proto->file_specific_info().file_md5(),
2278 GetTestFilePath("root_feed.json"),
2279 DRIVE_FILE_OK,
2280 test_util::TEST_CACHE_STATE_PRESENT,
2281 DriveCache::CACHE_TYPE_TMP);
2282
2283 // The file is obtained from the cache.
2284 // Make sure we don't call downloads at all.
2285 EXPECT_CALL(*mock_drive_service_, DownloadFile(_, _, _, _, _))
2286 .Times(0);
2287
2288 file_system_->GetFileByResourceId(entry_proto->resource_id(),
2289 callback,
2290 GetContentCallback());
2291 test_util::RunBlockingPoolTask();
2292
2293 EXPECT_EQ(REGULAR_FILE, callback_helper_->file_type_);
2294 EXPECT_EQ(downloaded_file.value(),
2295 callback_helper_->download_path_.value());
2296 }
2297
2298 TEST_F(GDataFileSystemTest, UpdateFileByResourceId_PersistentFile) {
2299 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2300 .Times(AtLeast(1)).WillRepeatedly(Return(kLotsOfSpace));
2301
2302 LoadRootFeedDocument("root_feed.json");
2303
2304 // This is a file defined in root_feed.json.
2305 const FilePath kFilePath(FILE_PATH_LITERAL("drive/File 1.txt"));
2306 const std::string kResourceId("file:2_file_resource_id");
2307 const std::string kMd5("3b4382ebefec6e743578c76bbd0575ce");
2308
2309 // Pin the file so it'll be store in "persistent" directory.
2310 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(kResourceId, kMd5)).Times(1);
2311 TestPin(kResourceId,
2312 kMd5,
2313 DRIVE_FILE_OK,
2314 test_util::TEST_CACHE_STATE_PINNED,
2315 DriveCache::CACHE_TYPE_TMP);
2316
2317 // First store a file to cache. A cache file will be created at:
2318 // GCache/v1/persistent/<kResourceId>.<kMd5>
2319 const FilePath original_cache_file_path =
2320 DriveCache::GetCacheRootPath(profile_.get())
2321 .AppendASCII("persistent")
2322 .AppendASCII(kResourceId + "." + kMd5);
2323 TestStoreToCache(kResourceId,
2324 kMd5,
2325 GetTestFilePath("root_feed.json"), // Anything works.
2326 DRIVE_FILE_OK,
2327 test_util::TEST_CACHE_STATE_PRESENT |
2328 test_util::TEST_CACHE_STATE_PINNED |
2329 test_util::TEST_CACHE_STATE_PERSISTENT,
2330 DriveCache::CACHE_TYPE_PERSISTENT);
2331 ASSERT_TRUE(file_util::PathExists(original_cache_file_path));
2332
2333 // Add the dirty bit. The cache file will be renamed to
2334 // GCache/v1/persistent/<kResourceId>.local
2335 TestMarkDirty(kResourceId,
2336 kMd5,
2337 DRIVE_FILE_OK,
2338 test_util::TEST_CACHE_STATE_PRESENT |
2339 test_util::TEST_CACHE_STATE_PINNED |
2340 test_util::TEST_CACHE_STATE_DIRTY |
2341 test_util::TEST_CACHE_STATE_PERSISTENT,
2342 DriveCache::CACHE_TYPE_PERSISTENT);
2343 const FilePath dirty_cache_file_path =
2344 DriveCache::GetCacheRootPath(profile_.get())
2345 .AppendASCII("persistent")
2346 .AppendASCII(kResourceId + ".local");
2347 ASSERT_FALSE(file_util::PathExists(original_cache_file_path));
2348 ASSERT_TRUE(file_util::PathExists(dirty_cache_file_path));
2349
2350 // Modify the cached file.
2351 const std::string kDummyCacheContent("modification to the cache");
2352 ASSERT_TRUE(file_util::WriteFile(dirty_cache_file_path,
2353 kDummyCacheContent.c_str(),
2354 kDummyCacheContent.size()));
2355
2356 // Commit the dirty bit. The cache file name remains the same
2357 // but a symlink will be created at:
2358 // GCache/v1/outgoing/<kResourceId>
2359 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(kResourceId)).Times(1);
2360 TestCommitDirty(kResourceId,
2361 kMd5,
2362 DRIVE_FILE_OK,
2363 test_util::TEST_CACHE_STATE_PRESENT |
2364 test_util::TEST_CACHE_STATE_PINNED |
2365 test_util::TEST_CACHE_STATE_DIRTY |
2366 test_util::TEST_CACHE_STATE_PERSISTENT,
2367 DriveCache::CACHE_TYPE_PERSISTENT);
2368 const FilePath outgoing_symlink_path =
2369 DriveCache::GetCacheRootPath(profile_.get())
2370 .AppendASCII("outgoing")
2371 .AppendASCII(kResourceId);
2372 ASSERT_TRUE(file_util::PathExists(dirty_cache_file_path));
2373 ASSERT_TRUE(file_util::PathExists(outgoing_symlink_path));
2374
2375 // Create a DocumentEntry, which is needed to mock
2376 // GDataUploaderInterface::UploadExistingFile().
2377 // TODO(satorux): This should be cleaned up. crbug.com/134240.
2378 DocumentEntry* document_entry = NULL;
2379 scoped_ptr<base::Value> value(LoadJSONFile("root_feed.json"));
2380 ASSERT_TRUE(value.get());
2381 base::DictionaryValue* as_dict = NULL;
2382 base::ListValue* entry_list = NULL;
2383 if (value->GetAsDictionary(&as_dict) &&
2384 as_dict->GetList("feed.entry", &entry_list)) {
2385 for (size_t i = 0; i < entry_list->GetSize(); ++i) {
2386 base::DictionaryValue* entry = NULL;
2387 std::string resource_id;
2388 if (entry_list->GetDictionary(i, &entry) &&
2389 entry->GetString("gd$resourceId.$t", &resource_id) &&
2390 resource_id == kResourceId) {
2391 // This will be deleted by UploadExistingFile().
2392 document_entry = DocumentEntry::CreateFrom(*entry);
2393 }
2394 }
2395 }
2396 ASSERT_TRUE(document_entry);
2397
2398 // The mock uploader will be used to simulate a file upload.
2399 EXPECT_CALL(*mock_uploader_, UploadExistingFile(
2400 GURL("https://file_link_resumable_edit_media/"),
2401 kFilePath,
2402 dirty_cache_file_path,
2403 kDummyCacheContent.size(), // The size after modification must be used.
2404 "audio/mpeg",
2405 _)) // callback
2406 .WillOnce(MockUploadExistingFile(
2407 DRIVE_FILE_OK,
2408 FilePath::FromUTF8Unsafe("drive/File1"),
2409 dirty_cache_file_path,
2410 document_entry));
2411
2412 // We'll notify the directory change to the observer upon completion.
2413 EXPECT_CALL(*mock_directory_observer_,
2414 OnDirectoryChanged(Eq(FilePath(kDriveRootDirectory)))).Times(1);
2415
2416 // The callback will be called upon completion of
2417 // UpdateFileByResourceId().
2418 FileOperationCallback callback =
2419 base::Bind(&CallbackHelper::FileOperationCallback,
2420 callback_helper_.get());
2421
2422 // Check the number of files in the root directory. We'll compare the
2423 // number after updating a file.
2424 scoped_ptr<DriveEntryProtoVector> root_directory_entries(
2425 ReadDirectoryByPathSync(FilePath::FromUTF8Unsafe("drive")));
2426 ASSERT_TRUE(root_directory_entries.get());
2427 const int num_files_in_root = CountFiles(*root_directory_entries);
2428
2429 file_system_->UpdateFileByResourceId(kResourceId, callback);
2430 test_util::RunBlockingPoolTask();
2431
2432 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2433 // Make sure that the number of files did not change (i.e. we updated an
2434 // existing file, rather than adding a new file. The number of files
2435 // increases if we don't handle the file update right).
2436 EXPECT_EQ(num_files_in_root, CountFiles(*root_directory_entries));
2437 // After the file is updated, the dirty bit is cleared, hence the symlink
2438 // should be gone.
2439 ASSERT_FALSE(file_util::PathExists(outgoing_symlink_path));
2440 }
2441
2442 TEST_F(GDataFileSystemTest, UpdateFileByResourceId_NonexistentFile) {
2443 LoadRootFeedDocument("root_feed.json");
2444
2445 // This is nonexistent in root_feed.json.
2446 const FilePath kFilePath(FILE_PATH_LITERAL("drive/Nonexistent.txt"));
2447 const std::string kResourceId("file:nonexistent_resource_id");
2448 const std::string kMd5("nonexistent_md5");
2449
2450 // The callback will be called upon completion of
2451 // UpdateFileByResourceId().
2452 FileOperationCallback callback =
2453 base::Bind(&CallbackHelper::FileOperationCallback,
2454 callback_helper_.get());
2455
2456 file_system_->UpdateFileByResourceId(kResourceId, callback);
2457 test_util::RunBlockingPoolTask();
2458 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
2459 }
2460
2461 TEST_F(GDataFileSystemTest, ContentSearch) {
2462 LoadRootFeedDocument("root_feed.json");
2463
2464 mock_drive_service_->set_search_result("search_result_feed.json");
2465
2466 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "foo", _, _))
2467 .Times(1);
2468
2469 const SearchResultPair kExpectedResults[] = {
2470 { "drive/Directory 1/SubDirectory File 1.txt", false },
2471 { "drive/Directory 1", true }
2472 };
2473
2474 SearchCallback callback = base::Bind(&DriveSearchCallback,
2475 &message_loop_, kExpectedResults, ARRAYSIZE_UNSAFE(kExpectedResults));
2476
2477 file_system_->Search("foo", GURL(), callback);
2478 message_loop_.Run(); // Wait to get our result.
2479 }
2480
2481 TEST_F(GDataFileSystemTest, ContentSearchWithNewEntry) {
2482 LoadRootFeedDocument("root_feed.json");
2483
2484 // Search result returning two entries "Directory 1/" and
2485 // "Directory 1/SubDirectory Newly Added File.txt". The latter is not
2486 // contained in the root feed.
2487 mock_drive_service_->set_search_result(
2488 "search_result_with_new_entry_feed.json");
2489
2490 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "foo", _, _))
2491 .Times(1);
2492
2493 // As the result of the first Search(), only entries in the current file
2494 // system snapshot are expected to be returned.
2495 const SearchResultPair kExpectedResults[] = {
2496 { "drive/Directory 1", true }
2497 };
2498
2499 // At the same time, unknown entry should trigger delta feed request.
2500 // This will cause notification to observers (e.g., File Browser) so that
2501 // they can request search again.
2502 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_)).Times(1);
2503 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "", _, _))
2504 .Times(1);
2505 EXPECT_CALL(*mock_webapps_registry_, UpdateFromFeed(_)).Times(1);
2506
2507 SearchCallback callback = base::Bind(&DriveSearchCallback,
2508 &message_loop_, kExpectedResults, ARRAYSIZE_UNSAFE(kExpectedResults));
2509
2510 file_system_->Search("foo", GURL(), callback);
2511 message_loop_.Run(); // Wait to get our result.
2512 }
2513
2514 TEST_F(GDataFileSystemTest, ContentSearchEmptyResult) {
2515 LoadRootFeedDocument("root_feed.json");
2516
2517 mock_drive_service_->set_search_result("empty_feed.json");
2518
2519 EXPECT_CALL(*mock_drive_service_, GetDocuments(Eq(GURL()), _, "foo", _, _))
2520 .Times(1);
2521
2522 const SearchResultPair* expected_results = NULL;
2523
2524 SearchCallback callback = base::Bind(&DriveSearchCallback,
2525 &message_loop_, expected_results, 0u);
2526
2527 file_system_->Search("foo", GURL(), callback);
2528 message_loop_.Run(); // Wait to get our result.
2529 }
2530
2531 TEST_F(GDataFileSystemTest, GetAvailableSpace) {
2532 GetAvailableSpaceCallback callback =
2533 base::Bind(&CallbackHelper::GetAvailableSpaceCallback,
2534 callback_helper_.get());
2535
2536 EXPECT_CALL(*mock_drive_service_, GetAccountMetadata(_));
2537
2538 file_system_->GetAvailableSpace(callback);
2539 test_util::RunBlockingPoolTask();
2540 EXPECT_EQ(GG_LONGLONG(6789012345), callback_helper_->quota_bytes_used_);
2541 EXPECT_EQ(GG_LONGLONG(9876543210), callback_helper_->quota_bytes_total_);
2542 }
2543
2544 TEST_F(GDataFileSystemTest, RequestDirectoryRefresh) {
2545 LoadRootFeedDocument("root_feed.json");
2546
2547 // We'll fetch documents in the root directory with its resource ID.
2548 EXPECT_CALL(*mock_drive_service_,
2549 GetDocuments(Eq(GURL()), _, _, kDriveRootDirectoryResourceId, _))
2550 .Times(1);
2551 // We'll notify the directory change to the observer.
2552 EXPECT_CALL(*mock_directory_observer_,
2553 OnDirectoryChanged(Eq(FilePath(kDriveRootDirectory)))).Times(1);
2554
2555 file_system_->RequestDirectoryRefresh(FilePath(kDriveRootDirectory));
2556 test_util::RunBlockingPoolTask();
2557 }
2558
2559 TEST_F(GDataFileSystemTest, OpenAndCloseFile) {
2560 LoadRootFeedDocument("root_feed.json");
2561
2562 OpenFileCallback callback =
2563 base::Bind(&CallbackHelper::OpenFileCallback,
2564 callback_helper_.get());
2565 FileOperationCallback close_file_callback =
2566 base::Bind(&CallbackHelper::CloseFileCallback,
2567 callback_helper_.get());
2568
2569 const FilePath kFileInRoot(FILE_PATH_LITERAL("drive/File 1.txt"));
2570 scoped_ptr<DriveEntryProto> entry_proto(GetEntryInfoByPathSync(kFileInRoot));
2571 FilePath downloaded_file = GetCachePathForFile(
2572 entry_proto->resource_id(),
2573 entry_proto->file_specific_info().file_md5());
2574 const int64 file_size = entry_proto->file_info().size();
2575 const std::string& file_resource_id =
2576 entry_proto->resource_id();
2577 const std::string& file_md5 = entry_proto->file_specific_info().file_md5();
2578
2579 // A dirty file is created on close.
2580 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(file_resource_id))
2581 .Times(1);
2582
2583 // Pretend we have enough space.
2584 EXPECT_CALL(*mock_free_disk_space_checker_, AmountOfFreeDiskSpace())
2585 .Times(2).WillRepeatedly(Return(file_size + kMinFreeSpace));
2586
2587 const std::string kExpectedFileData = "test file data";
2588 mock_drive_service_->set_file_data(new std::string(kExpectedFileData));
2589
2590 // Before Download starts metadata from server will be fetched.
2591 // We will read content url from the result.
2592 scoped_ptr<base::Value> document(LoadJSONFile("document_to_download.json"));
2593 SetExpectationsForGetDocumentEntry(&document, "file:2_file_resource_id");
2594
2595 // The file is obtained with the mock DriveService.
2596 EXPECT_CALL(*mock_drive_service_,
2597 DownloadFile(kFileInRoot,
2598 downloaded_file,
2599 GURL("https://file_content_url_changed/"),
2600 _, _))
2601 .Times(1);
2602
2603 // Open kFileInRoot ("drive/File 1.txt").
2604 file_system_->OpenFile(kFileInRoot, callback);
2605 message_loop_.Run();
2606 const FilePath opened_file_path = callback_helper_->opened_file_path_;
2607
2608 // Verify that the file was properly opened.
2609 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2610
2611 // Try to open the already opened file.
2612 file_system_->OpenFile(kFileInRoot, callback);
2613 message_loop_.Run();
2614
2615 // It must fail.
2616 EXPECT_EQ(DRIVE_FILE_ERROR_IN_USE, callback_helper_->last_error_);
2617
2618 // Verify that the file contents match the expected contents.
2619 std::string cache_file_data;
2620 EXPECT_TRUE(file_util::ReadFileToString(opened_file_path, &cache_file_data));
2621 EXPECT_EQ(kExpectedFileData, cache_file_data);
2622
2623 // Verify that the cache state was changed as expected.
2624 VerifyCacheStateAfterOpenFile(DRIVE_FILE_OK,
2625 file_resource_id,
2626 file_md5,
2627 opened_file_path);
2628
2629 // Close kFileInRoot ("drive/File 1.txt").
2630 file_system_->CloseFile(kFileInRoot, close_file_callback);
2631 message_loop_.Run();
2632
2633 // Verify that the file was properly closed.
2634 EXPECT_EQ(DRIVE_FILE_OK, callback_helper_->last_error_);
2635
2636 // Verify that the cache state was changed as expected.
2637 VerifyCacheStateAfterCloseFile(DRIVE_FILE_OK,
2638 file_resource_id,
2639 file_md5);
2640
2641 // Try to close the same file twice.
2642 file_system_->CloseFile(kFileInRoot, close_file_callback);
2643 message_loop_.Run();
2644
2645 // It must fail.
2646 EXPECT_EQ(DRIVE_FILE_ERROR_NOT_FOUND, callback_helper_->last_error_);
2647 }
2648
2649 } // namespace gdata
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/gdata/gdata_file_system_proxy.cc ('k') | chrome/browser/chromeos/gdata/gdata_protocol_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698