1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/drive/resource_metadata.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "chrome/browser/chromeos/drive/drive.pb.h"
16 #include "chrome/browser/chromeos/drive/file_system_util.h"
17 #include "chrome/browser/chromeos/drive/test_util.h"
18 #include "chrome/browser/google_apis/test_util.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "testing/gtest/include/gtest/gtest.h"
27 const char kTestRootResourceId[] = "test_root";
29 // The changestamp of the resource metadata used in
30 // ResourceMetadataTest.
31 const int64 kTestChangestamp = 100;
33 // Returns the sorted base names from |entries|.
34 std::vector<std::string> GetSortedBaseNames(
35 const ResourceEntryVector& entries) {
36 std::vector<std::string> base_names;
37 for (size_t i = 0; i < entries.size(); ++i)
38 base_names.push_back(entries[i].base_name());
39 std::sort(base_names.begin(), base_names.end());
44 // Creates a ResourceEntry for a directory with explicitly set resource_id.
45 ResourceEntry CreateDirectoryEntryWithResourceId(
46 const std::string& title,
47 const std::string& resource_id,
48 const std::string& parent_local_id) {
50 entry.set_title(title);
51 entry.set_resource_id(resource_id);
52 entry.set_parent_local_id(parent_local_id);
53 entry.mutable_file_info()->set_is_directory(true);
54 entry.mutable_directory_specific_info()->set_changestamp(kTestChangestamp);
58 // Creates a ResourceEntry for a directory.
59 ResourceEntry CreateDirectoryEntry(const std::string& title,
60 const std::string& parent_local_id) {
61 return CreateDirectoryEntryWithResourceId(
62 title, "id:" + title, parent_local_id);
65 // Creates a ResourceEntry for a file with explicitly set resource_id.
66 ResourceEntry CreateFileEntryWithResourceId(
67 const std::string& title,
68 const std::string& resource_id,
69 const std::string& parent_local_id) {
71 entry.set_title(title);
72 entry.set_resource_id(resource_id);
73 entry.set_parent_local_id(parent_local_id);
74 entry.mutable_file_info()->set_is_directory(false);
75 entry.mutable_file_info()->set_size(1024);
76 entry.mutable_file_specific_info()->set_md5("md5:" + title);
80 // Creates a ResourceEntry for a file.
81 ResourceEntry CreateFileEntry(const std::string& title,
82 const std::string& parent_local_id) {
83 return CreateFileEntryWithResourceId(title, "id:" + title, parent_local_id);
86 // Creates the following files/directories
89 // drive/root/dir1/dir3/
90 // drive/root/dir1/file4
91 // drive/root/dir1/file5
92 // drive/root/dir2/file6
93 // drive/root/dir2/file7
94 // drive/root/dir2/file8
95 // drive/root/dir1/dir3/file9
96 // drive/root/dir1/dir3/file10
97 void SetUpEntries(ResourceMetadata* resource_metadata) {
98 // Create mydrive root directory.
100 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
101 util::CreateMyDriveRootEntry(kTestRootResourceId), &local_id));
102 const std::string root_local_id = local_id;
104 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
105 CreateDirectoryEntry("dir1", root_local_id), &local_id));
106 const std::string local_id_dir1 = local_id;
108 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
109 CreateDirectoryEntry("dir2", root_local_id), &local_id));
110 const std::string local_id_dir2 = local_id;
112 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
113 CreateDirectoryEntry("dir3", local_id_dir1), &local_id));
114 const std::string local_id_dir3 = local_id;
116 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
117 CreateFileEntry("file4", local_id_dir1), &local_id));
118 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
119 CreateFileEntry("file5", local_id_dir1), &local_id));
121 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
122 CreateFileEntry("file6", local_id_dir2), &local_id));
123 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
124 CreateFileEntry("file7", local_id_dir2), &local_id));
125 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
126 CreateFileEntry("file8", local_id_dir2), &local_id));
128 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
129 CreateFileEntry("file9", local_id_dir3), &local_id));
130 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
131 CreateFileEntry("file10", local_id_dir3), &local_id));
133 ASSERT_EQ(FILE_ERROR_OK,
134 resource_metadata->SetLargestChangestamp(kTestChangestamp));
139 // Tests for methods invoked from the UI thread.
140 class ResourceMetadataTestOnUIThread : public testing::Test {
142 virtual void SetUp() OVERRIDE {
143 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
145 base::ThreadRestrictions::SetIOAllowed(false); // For strict thread check.
146 scoped_refptr<base::SequencedWorkerPool> pool =
147 content::BrowserThread::GetBlockingPool();
148 blocking_task_runner_ =
149 pool->GetSequencedTaskRunner(pool->GetSequenceToken());
151 metadata_storage_.reset(new ResourceMetadataStorage(
152 temp_dir_.path(), blocking_task_runner_.get()));
153 bool success = false;
154 base::PostTaskAndReplyWithResult(
155 blocking_task_runner_.get(),
157 base::Bind(&ResourceMetadataStorage::Initialize,
158 base::Unretained(metadata_storage_.get())),
159 google_apis::test_util::CreateCopyResultCallback(&success));
160 test_util::RunBlockingPoolTask();
161 ASSERT_TRUE(success);
163 resource_metadata_.reset(new ResourceMetadata(metadata_storage_.get(),
164 blocking_task_runner_));
166 FileError error = FILE_ERROR_FAILED;
167 base::PostTaskAndReplyWithResult(
168 blocking_task_runner_.get(),
170 base::Bind(&ResourceMetadata::Initialize,
171 base::Unretained(resource_metadata_.get())),
172 google_apis::test_util::CreateCopyResultCallback(&error));
173 test_util::RunBlockingPoolTask();
174 ASSERT_EQ(FILE_ERROR_OK, error);
176 blocking_task_runner_->PostTask(
178 base::Bind(&SetUpEntries,
179 base::Unretained(resource_metadata_.get())));
180 test_util::RunBlockingPoolTask();
183 virtual void TearDown() OVERRIDE {
184 metadata_storage_.reset();
185 resource_metadata_.reset();
186 base::ThreadRestrictions::SetIOAllowed(true);
189 content::TestBrowserThreadBundle thread_bundle_;
190 base::ScopedTempDir temp_dir_;
191 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
192 scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
194 scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
198 TEST_F(ResourceMetadataTestOnUIThread, GetResourceEntryByPath) {
199 // Confirm that an existing file is found.
200 FileError error = FILE_ERROR_FAILED;
201 scoped_ptr<ResourceEntry> entry;
202 resource_metadata_->GetResourceEntryByPathOnUIThread(
203 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
204 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
205 test_util::RunBlockingPoolTask();
206 EXPECT_EQ(FILE_ERROR_OK, error);
207 ASSERT_TRUE(entry.get());
208 EXPECT_EQ("file4", entry->base_name());
210 // Confirm that a non existing file is not found.
211 error = FILE_ERROR_FAILED;
213 resource_metadata_->GetResourceEntryByPathOnUIThread(
214 base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existing"),
215 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
216 test_util::RunBlockingPoolTask();
217 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
218 EXPECT_FALSE(entry.get());
220 // Confirm that the root is found.
221 error = FILE_ERROR_FAILED;
223 resource_metadata_->GetResourceEntryByPathOnUIThread(
224 base::FilePath::FromUTF8Unsafe("drive"),
225 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
226 test_util::RunBlockingPoolTask();
227 EXPECT_EQ(FILE_ERROR_OK, error);
228 EXPECT_TRUE(entry.get());
230 // Confirm that a non existing file is not found at the root level.
231 error = FILE_ERROR_FAILED;
233 resource_metadata_->GetResourceEntryByPathOnUIThread(
234 base::FilePath::FromUTF8Unsafe("non_existing"),
235 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
236 test_util::RunBlockingPoolTask();
237 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
238 EXPECT_FALSE(entry.get());
240 // Confirm that an entry is not found with a wrong root.
241 error = FILE_ERROR_FAILED;
243 resource_metadata_->GetResourceEntryByPathOnUIThread(
244 base::FilePath::FromUTF8Unsafe("non_existing/root"),
245 google_apis::test_util::CreateCopyResultCallback(&error, &entry));
246 test_util::RunBlockingPoolTask();
247 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
248 EXPECT_FALSE(entry.get());
251 TEST_F(ResourceMetadataTestOnUIThread, ReadDirectoryByPath) {
252 // Confirm that an existing directory is found.
253 FileError error = FILE_ERROR_FAILED;
254 scoped_ptr<ResourceEntryVector> entries;
255 resource_metadata_->ReadDirectoryByPathOnUIThread(
256 base::FilePath::FromUTF8Unsafe("drive/root/dir1"),
257 google_apis::test_util::CreateCopyResultCallback(&error, &entries));
258 test_util::RunBlockingPoolTask();
259 EXPECT_EQ(FILE_ERROR_OK, error);
260 ASSERT_TRUE(entries.get());
261 ASSERT_EQ(3U, entries->size());
262 // The order is not guaranteed so we should sort the base names.
263 std::vector<std::string> base_names = GetSortedBaseNames(*entries);
264 EXPECT_EQ("dir3", base_names[0]);
265 EXPECT_EQ("file4", base_names[1]);
266 EXPECT_EQ("file5", base_names[2]);
268 // Confirm that a non existing directory is not found.
269 error = FILE_ERROR_FAILED;
271 resource_metadata_->ReadDirectoryByPathOnUIThread(
272 base::FilePath::FromUTF8Unsafe("drive/root/non_existing"),
273 google_apis::test_util::CreateCopyResultCallback(&error, &entries));
274 test_util::RunBlockingPoolTask();
275 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
276 EXPECT_FALSE(entries.get());
278 // Confirm that reading a file results in FILE_ERROR_NOT_A_DIRECTORY.
279 error = FILE_ERROR_FAILED;
281 resource_metadata_->ReadDirectoryByPathOnUIThread(
282 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
283 google_apis::test_util::CreateCopyResultCallback(&error, &entries));
284 test_util::RunBlockingPoolTask();
285 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error);
286 EXPECT_FALSE(entries.get());
289 // Tests for methods running on the blocking task runner.
290 class ResourceMetadataTest : public testing::Test {
292 virtual void SetUp() OVERRIDE {
293 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
295 metadata_storage_.reset(new ResourceMetadataStorage(
296 temp_dir_.path(), base::MessageLoopProxy::current().get()));
297 ASSERT_TRUE(metadata_storage_->Initialize());
299 resource_metadata_.reset(new ResourceMetadata(
300 metadata_storage_.get(), base::MessageLoopProxy::current()));
302 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
304 SetUpEntries(resource_metadata_.get());
307 base::ScopedTempDir temp_dir_;
308 content::TestBrowserThreadBundle thread_bundle_;
309 scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
311 scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
315 TEST_F(ResourceMetadataTest, LargestChangestamp) {
316 const int64 kChangestamp = 123456;
317 EXPECT_EQ(FILE_ERROR_OK,
318 resource_metadata_->SetLargestChangestamp(kChangestamp));
319 EXPECT_EQ(kChangestamp, resource_metadata_->GetLargestChangestamp());
322 TEST_F(ResourceMetadataTest, RefreshEntry) {
323 base::FilePath drive_file_path;
328 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
329 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &file_id));
330 EXPECT_EQ(FILE_ERROR_OK,
331 resource_metadata_->GetResourceEntryById(file_id, &entry));
332 EXPECT_EQ("file9", entry.base_name());
333 EXPECT_TRUE(!entry.file_info().is_directory());
334 EXPECT_EQ("md5:file9", entry.file_specific_info().md5());
337 ResourceEntry file_entry(entry);
338 file_entry.set_title("file100");
339 EXPECT_EQ(FILE_ERROR_OK,
340 resource_metadata_->RefreshEntry(file_entry));
342 EXPECT_EQ("drive/root/dir1/dir3/file100",
343 resource_metadata_->GetFilePath(file_id).AsUTF8Unsafe());
345 EXPECT_EQ(FILE_ERROR_OK,
346 resource_metadata_->GetResourceEntryById(file_id, &entry));
347 EXPECT_EQ("file100", entry.base_name());
348 EXPECT_TRUE(!entry.file_info().is_directory());
349 EXPECT_EQ("md5:file9", entry.file_specific_info().md5());
351 // Update the file md5.
352 const std::string updated_md5("md5:updated");
354 file_entry.mutable_file_specific_info()->set_md5(updated_md5);
355 EXPECT_EQ(FILE_ERROR_OK,
356 resource_metadata_->RefreshEntry(file_entry));
358 EXPECT_EQ("drive/root/dir1/dir3/file100",
359 resource_metadata_->GetFilePath(file_id).AsUTF8Unsafe());
361 EXPECT_EQ(FILE_ERROR_OK,
362 resource_metadata_->GetResourceEntryById(file_id, &entry));
363 EXPECT_EQ("file100", entry.base_name());
364 EXPECT_TRUE(!entry.file_info().is_directory());
365 EXPECT_EQ(updated_md5, entry.file_specific_info().md5());
367 // Make sure we get the same thing from GetResourceEntryByPath.
369 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
370 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"), &entry));
371 EXPECT_EQ("file100", entry.base_name());
372 ASSERT_TRUE(!entry.file_info().is_directory());
373 EXPECT_EQ(updated_md5, entry.file_specific_info().md5());
378 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
379 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &dir_id));
380 EXPECT_EQ(FILE_ERROR_OK,
381 resource_metadata_->GetResourceEntryById(dir_id, &entry));
382 EXPECT_EQ("dir2", entry.base_name());
383 ASSERT_TRUE(entry.file_info().is_directory());
387 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
388 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_id));
390 // Change the name to dir100 and change the parent to drive/dir1/dir3.
391 ResourceEntry dir_entry(entry);
392 dir_entry.set_title("dir100");
393 dir_entry.set_parent_local_id(dir3_id);
394 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(dir_entry));
396 EXPECT_EQ("drive/root/dir1/dir3/dir100",
397 resource_metadata_->GetFilePath(dir_id).AsUTF8Unsafe());
399 EXPECT_EQ(FILE_ERROR_OK,
400 resource_metadata_->GetResourceEntryById(dir_id, &entry));
401 EXPECT_EQ("dir100", entry.base_name());
402 EXPECT_TRUE(entry.file_info().is_directory());
403 EXPECT_EQ("id:dir2", entry.resource_id());
405 // Make sure the children have moved over. Test file6.
407 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
408 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/dir100/file6"),
410 EXPECT_EQ("file6", entry.base_name());
412 // Make sure dir2 no longer exists.
413 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath(
414 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry));
416 // Make sure that directory cannot move under a file.
417 dir_entry.set_parent_local_id(file_id);
418 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY,
419 resource_metadata_->RefreshEntry(dir_entry));
421 // Cannot refresh root.
423 dir_entry.set_resource_id(util::kDriveGrandRootSpecialResourceId);
424 dir_entry.set_local_id(util::kDriveGrandRootSpecialResourceId);
425 dir_entry.set_title("new-root-name");
426 dir_entry.set_parent_local_id(dir3_id);
427 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION,
428 resource_metadata_->RefreshEntry(dir_entry));
431 TEST_F(ResourceMetadataTest, GetSubDirectoriesRecursively) {
432 std::set<base::FilePath> sub_directories;
434 // file9: not a directory, so no children.
435 std::string local_id;
436 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
437 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &local_id));
438 resource_metadata_->GetSubDirectoriesRecursively(local_id, &sub_directories);
439 EXPECT_TRUE(sub_directories.empty());
441 // dir2: no child directories.
442 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
443 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &local_id));
444 resource_metadata_->GetSubDirectoriesRecursively(local_id, &sub_directories);
445 EXPECT_TRUE(sub_directories.empty());
446 const std::string dir2_id = local_id;
448 // dir1: dir3 is the only child
449 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
450 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id));
451 resource_metadata_->GetSubDirectoriesRecursively(local_id, &sub_directories);
452 EXPECT_EQ(1u, sub_directories.size());
453 EXPECT_EQ(1u, sub_directories.count(
454 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3")));
455 sub_directories.clear();
457 // Add a few more directories to make sure deeper nesting works.
460 // dir2/dir101/dir102
461 // dir2/dir101/dir103
462 // dir2/dir101/dir104
463 // dir2/dir101/dir104/dir105
464 // dir2/dir101/dir104/dir105/dir106
465 // dir2/dir101/dir104/dir105/dir106/dir107
466 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
467 CreateDirectoryEntry("dir100", dir2_id), &local_id));
468 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
469 CreateDirectoryEntry("dir101", dir2_id), &local_id));
470 const std::string dir101_id = local_id;
471 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
472 CreateDirectoryEntry("dir102", dir101_id), &local_id));
473 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
474 CreateDirectoryEntry("dir103", dir101_id), &local_id));
475 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
476 CreateDirectoryEntry("dir104", dir101_id), &local_id));
477 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
478 CreateDirectoryEntry("dir105", local_id), &local_id));
479 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
480 CreateDirectoryEntry("dir106", local_id), &local_id));
481 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
482 CreateDirectoryEntry("dir107", local_id), &local_id));
484 resource_metadata_->GetSubDirectoriesRecursively(dir2_id, &sub_directories);
485 EXPECT_EQ(8u, sub_directories.size());
486 EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe(
487 "drive/root/dir2/dir101")));
488 EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe(
489 "drive/root/dir2/dir101/dir104")));
490 EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe(
491 "drive/root/dir2/dir101/dir104/dir105/dir106/dir107")));
494 TEST_F(ResourceMetadataTest, AddEntry) {
495 base::FilePath drive_file_path;
497 // Add a file to dir3.
498 std::string local_id;
499 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
500 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &local_id));
501 ResourceEntry file_entry = CreateFileEntry("file100", local_id);
502 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(file_entry, &local_id));
503 EXPECT_EQ("drive/root/dir1/dir3/file100",
504 resource_metadata_->GetFilePath(local_id).AsUTF8Unsafe());
507 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
508 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id));
509 ResourceEntry dir_entry = CreateDirectoryEntry("dir101", local_id);
510 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(dir_entry, &local_id));
511 EXPECT_EQ("drive/root/dir1/dir101",
512 resource_metadata_->GetFilePath(local_id).AsUTF8Unsafe());
514 // Add to an invalid parent.
515 ResourceEntry file_entry3 = CreateFileEntry("file103", "id:invalid");
516 EXPECT_EQ(FILE_ERROR_NOT_FOUND,
517 resource_metadata_->AddEntry(file_entry3, &local_id));
519 // Add an existing file.
520 EXPECT_EQ(FILE_ERROR_EXISTS,
521 resource_metadata_->AddEntry(file_entry, &local_id));
524 TEST_F(ResourceMetadataTest, RemoveEntry) {
525 // Make sure file9 is found.
526 std::string file9_local_id;
527 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
528 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"),
531 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
532 file9_local_id, &entry));
533 EXPECT_EQ("file9", entry.base_name());
536 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(file9_local_id));
538 // file9 should no longer exist.
539 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
540 file9_local_id, &entry));
543 std::string dir3_local_id;
544 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
545 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_local_id));
546 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
547 dir3_local_id, &entry));
548 EXPECT_EQ("dir3", entry.base_name());
551 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(dir3_local_id));
553 // dir3 should no longer exist.
554 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
555 dir3_local_id, &entry));
557 // Remove unknown local_id using RemoveEntry.
558 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->RemoveEntry("foo"));
560 // Try removing root. This should fail.
561 EXPECT_EQ(FILE_ERROR_ACCESS_DENIED, resource_metadata_->RemoveEntry(
562 util::kDriveGrandRootSpecialResourceId));
565 TEST_F(ResourceMetadataTest, GetResourceEntryById_RootDirectory) {
566 // Look up the root directory by its ID.
568 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
569 util::kDriveGrandRootSpecialResourceId, &entry));
570 EXPECT_EQ("drive", entry.base_name());
573 TEST_F(ResourceMetadataTest, GetResourceEntryById) {
574 // Get file4 by path.
575 std::string local_id;
576 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
577 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &local_id));
579 // Confirm that an existing file is found.
581 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
583 EXPECT_EQ("file4", entry.base_name());
585 // Confirm that a non existing file is not found.
586 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
587 "file:non_existing", &entry));
590 TEST_F(ResourceMetadataTest, Iterate) {
591 scoped_ptr<ResourceMetadata::Iterator> it = resource_metadata_->GetIterator();
594 int file_count = 0, directory_count = 0;
595 for (; !it->IsAtEnd(); it->Advance()) {
596 if (!it->GetValue().file_info().is_directory())
602 EXPECT_EQ(7, file_count);
603 EXPECT_EQ(6, directory_count);
606 TEST_F(ResourceMetadataTest, DuplicatedNames) {
607 std::string root_local_id;
608 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
609 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id));
613 // When multiple entries with the same title are added in a single directory,
614 // their base_names are de-duped.
616 // - drive/root/foo (1)
617 std::string dir_id_0;
618 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
619 CreateDirectoryEntryWithResourceId(
620 "foo", "foo0", root_local_id), &dir_id_0));
621 std::string dir_id_1;
622 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
623 CreateDirectoryEntryWithResourceId(
624 "foo", "foo1", root_local_id), &dir_id_1));
626 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
628 EXPECT_EQ("foo", entry.base_name());
629 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
631 EXPECT_EQ("foo (1)", entry.base_name());
633 // - drive/root/foo/bar.txt
634 // - drive/root/foo/bar (1).txt
635 // - drive/root/foo/bar (2).txt
636 std::string file_id_0;
637 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
638 CreateFileEntryWithResourceId(
639 "bar.txt", "bar0", dir_id_0), &file_id_0));
640 std::string file_id_1;
641 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
642 CreateFileEntryWithResourceId(
643 "bar.txt", "bar1", dir_id_0), &file_id_1));
644 std::string file_id_2;
645 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
646 CreateFileEntryWithResourceId(
647 "bar.txt", "bar2", dir_id_0), &file_id_2));
649 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
651 EXPECT_EQ("bar.txt", entry.base_name());
652 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
654 EXPECT_EQ("bar (1).txt", entry.base_name());
655 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
657 EXPECT_EQ("bar (2).txt", entry.base_name());
659 // Same name but different parent. No renaming.
660 // - drive/root/foo (1)/bar.txt
661 std::string file_id_3;
662 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
663 CreateFileEntryWithResourceId(
664 "bar.txt", "bar3", dir_id_1), &file_id_3));
666 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
668 EXPECT_EQ("bar.txt", entry.base_name());
670 // Checks that the entries can be looked up by the de-duped paths.
671 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
672 base::FilePath::FromUTF8Unsafe("drive/root/foo/bar (2).txt"), &entry));
673 EXPECT_EQ("bar2", entry.resource_id());
674 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
675 base::FilePath::FromUTF8Unsafe("drive/root/foo (1)/bar.txt"), &entry));
676 EXPECT_EQ("bar3", entry.resource_id());
679 TEST_F(ResourceMetadataTest, EncodedNames) {
680 std::string root_local_id;
681 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
682 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id));
687 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
688 CreateDirectoryEntry("\\(^o^)/", root_local_id), &dir_id));
689 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
691 EXPECT_EQ("\\(^o^)\xE2\x88\x95", entry.base_name());
694 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
695 CreateFileEntryWithResourceId("Slash /.txt", "myfile", dir_id),
697 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
699 EXPECT_EQ("Slash \xE2\x88\x95.txt", entry.base_name());
701 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
702 base::FilePath::FromUTF8Unsafe(
703 "drive/root/\\(^o^)\xE2\x88\x95/Slash \xE2\x88\x95.txt"),
705 EXPECT_EQ("myfile", entry.resource_id());
708 TEST_F(ResourceMetadataTest, Reset) {
709 // The grand root has "root" which is not empty.
710 std::vector<ResourceEntry> entries;
711 ASSERT_EQ(FILE_ERROR_OK,
712 resource_metadata_->ReadDirectoryByPath(
713 base::FilePath::FromUTF8Unsafe("drive/root"), &entries));
714 ASSERT_FALSE(entries.empty());
717 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->Reset());
719 // change stamp should be reset.
720 EXPECT_EQ(0, resource_metadata_->GetLargestChangestamp());
722 // root should continue to exist.
724 ASSERT_EQ(FILE_ERROR_OK,
725 resource_metadata_->GetResourceEntryByPath(
726 base::FilePath::FromUTF8Unsafe("drive"), &entry));
727 EXPECT_EQ("drive", entry.base_name());
728 ASSERT_TRUE(entry.file_info().is_directory());
729 EXPECT_EQ(util::kDriveGrandRootSpecialResourceId, entry.resource_id());
731 // There is "other" under "drive".
732 ASSERT_EQ(FILE_ERROR_OK,
733 resource_metadata_->ReadDirectoryByPath(
734 base::FilePath::FromUTF8Unsafe("drive"), &entries));
735 EXPECT_EQ(1U, entries.size());
737 // The "other" directory should be empty.
738 ASSERT_EQ(FILE_ERROR_OK,
739 resource_metadata_->ReadDirectoryByPath(
740 base::FilePath::FromUTF8Unsafe("drive/other"), &entries));
741 EXPECT_TRUE(entries.empty());
744 } // namespace internal