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 "content/public/browser/browser_thread.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "google_apis/drive/test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
27 // The changestamp of the resource metadata used in
28 // ResourceMetadataTest.
29 const int64 kTestChangestamp
= 100;
31 // Returns the sorted base names from |entries|.
32 std::vector
<std::string
> GetSortedBaseNames(
33 const ResourceEntryVector
& entries
) {
34 std::vector
<std::string
> base_names
;
35 for (size_t i
= 0; i
< entries
.size(); ++i
)
36 base_names
.push_back(entries
[i
].base_name());
37 std::sort(base_names
.begin(), base_names
.end());
42 // Creates a ResourceEntry for a directory with explicitly set resource_id.
43 ResourceEntry
CreateDirectoryEntryWithResourceId(
44 const std::string
& title
,
45 const std::string
& resource_id
,
46 const std::string
& parent_local_id
) {
48 entry
.set_title(title
);
49 entry
.set_resource_id(resource_id
);
50 entry
.set_parent_local_id(parent_local_id
);
51 entry
.mutable_file_info()->set_is_directory(true);
52 entry
.mutable_directory_specific_info()->set_changestamp(kTestChangestamp
);
56 // Creates a ResourceEntry for a directory.
57 ResourceEntry
CreateDirectoryEntry(const std::string
& title
,
58 const std::string
& parent_local_id
) {
59 return CreateDirectoryEntryWithResourceId(
60 title
, "id:" + title
, parent_local_id
);
63 // Creates a ResourceEntry for a file with explicitly set resource_id.
64 ResourceEntry
CreateFileEntryWithResourceId(
65 const std::string
& title
,
66 const std::string
& resource_id
,
67 const std::string
& parent_local_id
) {
69 entry
.set_title(title
);
70 entry
.set_resource_id(resource_id
);
71 entry
.set_parent_local_id(parent_local_id
);
72 entry
.mutable_file_info()->set_is_directory(false);
73 entry
.mutable_file_info()->set_size(1024);
74 entry
.mutable_file_specific_info()->set_md5("md5:" + title
);
78 // Creates a ResourceEntry for a file.
79 ResourceEntry
CreateFileEntry(const std::string
& title
,
80 const std::string
& parent_local_id
) {
81 return CreateFileEntryWithResourceId(title
, "id:" + title
, parent_local_id
);
84 // Creates the following files/directories
87 // drive/root/dir1/dir3/
88 // drive/root/dir1/file4
89 // drive/root/dir1/file5
90 // drive/root/dir2/file6
91 // drive/root/dir2/file7
92 // drive/root/dir2/file8
93 // drive/root/dir1/dir3/file9
94 // drive/root/dir1/dir3/file10
95 void SetUpEntries(ResourceMetadata
* resource_metadata
) {
97 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->GetIdByPath(
98 util::GetDriveMyDriveRootPath(), &local_id
));
99 const std::string root_local_id
= local_id
;
101 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
102 CreateDirectoryEntry("dir1", root_local_id
), &local_id
));
103 const std::string local_id_dir1
= local_id
;
105 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
106 CreateDirectoryEntry("dir2", root_local_id
), &local_id
));
107 const std::string local_id_dir2
= local_id
;
109 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
110 CreateDirectoryEntry("dir3", local_id_dir1
), &local_id
));
111 const std::string local_id_dir3
= local_id
;
113 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
114 CreateFileEntry("file4", local_id_dir1
), &local_id
));
115 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
116 CreateFileEntry("file5", local_id_dir1
), &local_id
));
118 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
119 CreateFileEntry("file6", local_id_dir2
), &local_id
));
120 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
121 CreateFileEntry("file7", local_id_dir2
), &local_id
));
122 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
123 CreateFileEntry("file8", local_id_dir2
), &local_id
));
125 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
126 CreateFileEntry("file9", local_id_dir3
), &local_id
));
127 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
128 CreateFileEntry("file10", local_id_dir3
), &local_id
));
130 ASSERT_EQ(FILE_ERROR_OK
,
131 resource_metadata
->SetLargestChangestamp(kTestChangestamp
));
136 // Tests for methods invoked from the UI thread.
137 class ResourceMetadataTestOnUIThread
: public testing::Test
{
139 virtual void SetUp() OVERRIDE
{
140 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
142 base::ThreadRestrictions::SetIOAllowed(false); // For strict thread check.
143 scoped_refptr
<base::SequencedWorkerPool
> pool
=
144 content::BrowserThread::GetBlockingPool();
145 blocking_task_runner_
=
146 pool
->GetSequencedTaskRunner(pool
->GetSequenceToken());
148 metadata_storage_
.reset(new ResourceMetadataStorage(
149 temp_dir_
.path(), blocking_task_runner_
.get()));
150 bool success
= false;
151 base::PostTaskAndReplyWithResult(
152 blocking_task_runner_
.get(),
154 base::Bind(&ResourceMetadataStorage::Initialize
,
155 base::Unretained(metadata_storage_
.get())),
156 google_apis::test_util::CreateCopyResultCallback(&success
));
157 test_util::RunBlockingPoolTask();
158 ASSERT_TRUE(success
);
160 resource_metadata_
.reset(new ResourceMetadata(metadata_storage_
.get(),
161 blocking_task_runner_
));
163 FileError error
= FILE_ERROR_FAILED
;
164 base::PostTaskAndReplyWithResult(
165 blocking_task_runner_
.get(),
167 base::Bind(&ResourceMetadata::Initialize
,
168 base::Unretained(resource_metadata_
.get())),
169 google_apis::test_util::CreateCopyResultCallback(&error
));
170 test_util::RunBlockingPoolTask();
171 ASSERT_EQ(FILE_ERROR_OK
, error
);
173 blocking_task_runner_
->PostTask(
175 base::Bind(&SetUpEntries
,
176 base::Unretained(resource_metadata_
.get())));
177 test_util::RunBlockingPoolTask();
180 virtual void TearDown() OVERRIDE
{
181 metadata_storage_
.reset();
182 resource_metadata_
.reset();
183 base::ThreadRestrictions::SetIOAllowed(true);
186 content::TestBrowserThreadBundle thread_bundle_
;
187 base::ScopedTempDir temp_dir_
;
188 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner_
;
189 scoped_ptr
<ResourceMetadataStorage
, test_util::DestroyHelperForTests
>
191 scoped_ptr
<ResourceMetadata
, test_util::DestroyHelperForTests
>
195 TEST_F(ResourceMetadataTestOnUIThread
, GetResourceEntryByPath
) {
196 // Confirm that an existing file is found.
197 FileError error
= FILE_ERROR_FAILED
;
198 scoped_ptr
<ResourceEntry
> entry
;
199 resource_metadata_
->GetResourceEntryByPathOnUIThread(
200 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
201 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
202 test_util::RunBlockingPoolTask();
203 EXPECT_EQ(FILE_ERROR_OK
, error
);
204 ASSERT_TRUE(entry
.get());
205 EXPECT_EQ("file4", entry
->base_name());
207 // Confirm that a non existing file is not found.
208 error
= FILE_ERROR_FAILED
;
210 resource_metadata_
->GetResourceEntryByPathOnUIThread(
211 base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existing"),
212 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
213 test_util::RunBlockingPoolTask();
214 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, error
);
215 EXPECT_FALSE(entry
.get());
217 // Confirm that the root is found.
218 error
= FILE_ERROR_FAILED
;
220 resource_metadata_
->GetResourceEntryByPathOnUIThread(
221 base::FilePath::FromUTF8Unsafe("drive"),
222 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
223 test_util::RunBlockingPoolTask();
224 EXPECT_EQ(FILE_ERROR_OK
, error
);
225 EXPECT_TRUE(entry
.get());
227 // Confirm that a non existing file is not found at the root level.
228 error
= FILE_ERROR_FAILED
;
230 resource_metadata_
->GetResourceEntryByPathOnUIThread(
231 base::FilePath::FromUTF8Unsafe("non_existing"),
232 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
233 test_util::RunBlockingPoolTask();
234 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, error
);
235 EXPECT_FALSE(entry
.get());
237 // Confirm that an entry is not found with a wrong root.
238 error
= FILE_ERROR_FAILED
;
240 resource_metadata_
->GetResourceEntryByPathOnUIThread(
241 base::FilePath::FromUTF8Unsafe("non_existing/root"),
242 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
243 test_util::RunBlockingPoolTask();
244 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, error
);
245 EXPECT_FALSE(entry
.get());
248 TEST_F(ResourceMetadataTestOnUIThread
, ReadDirectoryByPath
) {
249 // Confirm that an existing directory is found.
250 FileError error
= FILE_ERROR_FAILED
;
251 scoped_ptr
<ResourceEntryVector
> entries
;
252 resource_metadata_
->ReadDirectoryByPathOnUIThread(
253 base::FilePath::FromUTF8Unsafe("drive/root/dir1"),
254 google_apis::test_util::CreateCopyResultCallback(&error
, &entries
));
255 test_util::RunBlockingPoolTask();
256 EXPECT_EQ(FILE_ERROR_OK
, error
);
257 ASSERT_TRUE(entries
.get());
258 ASSERT_EQ(3U, entries
->size());
259 // The order is not guaranteed so we should sort the base names.
260 std::vector
<std::string
> base_names
= GetSortedBaseNames(*entries
);
261 EXPECT_EQ("dir3", base_names
[0]);
262 EXPECT_EQ("file4", base_names
[1]);
263 EXPECT_EQ("file5", base_names
[2]);
265 // Confirm that a non existing directory is not found.
266 error
= FILE_ERROR_FAILED
;
268 resource_metadata_
->ReadDirectoryByPathOnUIThread(
269 base::FilePath::FromUTF8Unsafe("drive/root/non_existing"),
270 google_apis::test_util::CreateCopyResultCallback(&error
, &entries
));
271 test_util::RunBlockingPoolTask();
272 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, error
);
273 EXPECT_FALSE(entries
.get());
275 // Confirm that reading a file results in FILE_ERROR_NOT_A_DIRECTORY.
276 error
= FILE_ERROR_FAILED
;
278 resource_metadata_
->ReadDirectoryByPathOnUIThread(
279 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"),
280 google_apis::test_util::CreateCopyResultCallback(&error
, &entries
));
281 test_util::RunBlockingPoolTask();
282 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY
, error
);
283 EXPECT_FALSE(entries
.get());
286 // Tests for methods running on the blocking task runner.
287 class ResourceMetadataTest
: public testing::Test
{
289 virtual void SetUp() OVERRIDE
{
290 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
292 metadata_storage_
.reset(new ResourceMetadataStorage(
293 temp_dir_
.path(), base::MessageLoopProxy::current().get()));
294 ASSERT_TRUE(metadata_storage_
->Initialize());
296 resource_metadata_
.reset(new ResourceMetadata(
297 metadata_storage_
.get(), base::MessageLoopProxy::current()));
299 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->Initialize());
301 SetUpEntries(resource_metadata_
.get());
304 base::ScopedTempDir temp_dir_
;
305 content::TestBrowserThreadBundle thread_bundle_
;
306 scoped_ptr
<ResourceMetadataStorage
, test_util::DestroyHelperForTests
>
308 scoped_ptr
<ResourceMetadata
, test_util::DestroyHelperForTests
>
312 TEST_F(ResourceMetadataTest
, LargestChangestamp
) {
313 const int64 kChangestamp
= 123456;
314 EXPECT_EQ(FILE_ERROR_OK
,
315 resource_metadata_
->SetLargestChangestamp(kChangestamp
));
316 EXPECT_EQ(kChangestamp
, resource_metadata_
->GetLargestChangestamp());
319 TEST_F(ResourceMetadataTest
, RefreshEntry
) {
320 base::FilePath drive_file_path
;
325 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
326 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &file_id
));
327 EXPECT_EQ(FILE_ERROR_OK
,
328 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
329 EXPECT_EQ("file9", entry
.base_name());
330 EXPECT_TRUE(!entry
.file_info().is_directory());
331 EXPECT_EQ("md5:file9", entry
.file_specific_info().md5());
334 ResourceEntry
file_entry(entry
);
335 file_entry
.set_title("file100");
336 EXPECT_EQ(FILE_ERROR_OK
,
337 resource_metadata_
->RefreshEntry(file_entry
));
339 EXPECT_EQ("drive/root/dir1/dir3/file100",
340 resource_metadata_
->GetFilePath(file_id
).AsUTF8Unsafe());
342 EXPECT_EQ(FILE_ERROR_OK
,
343 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
344 EXPECT_EQ("file100", entry
.base_name());
345 EXPECT_TRUE(!entry
.file_info().is_directory());
346 EXPECT_EQ("md5:file9", entry
.file_specific_info().md5());
348 // Update the file md5.
349 const std::string
updated_md5("md5:updated");
351 file_entry
.mutable_file_specific_info()->set_md5(updated_md5
);
352 EXPECT_EQ(FILE_ERROR_OK
,
353 resource_metadata_
->RefreshEntry(file_entry
));
355 EXPECT_EQ("drive/root/dir1/dir3/file100",
356 resource_metadata_
->GetFilePath(file_id
).AsUTF8Unsafe());
358 EXPECT_EQ(FILE_ERROR_OK
,
359 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
360 EXPECT_EQ("file100", entry
.base_name());
361 EXPECT_TRUE(!entry
.file_info().is_directory());
362 EXPECT_EQ(updated_md5
, entry
.file_specific_info().md5());
364 // Make sure we get the same thing from GetResourceEntryByPath.
366 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
367 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"), &entry
));
368 EXPECT_EQ("file100", entry
.base_name());
369 ASSERT_TRUE(!entry
.file_info().is_directory());
370 EXPECT_EQ(updated_md5
, entry
.file_specific_info().md5());
375 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
376 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &dir_id
));
377 EXPECT_EQ(FILE_ERROR_OK
,
378 resource_metadata_
->GetResourceEntryById(dir_id
, &entry
));
379 EXPECT_EQ("dir2", entry
.base_name());
380 ASSERT_TRUE(entry
.file_info().is_directory());
384 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
385 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_id
));
387 // Change the name to dir100 and change the parent to drive/dir1/dir3.
388 ResourceEntry
dir_entry(entry
);
389 dir_entry
.set_title("dir100");
390 dir_entry
.set_parent_local_id(dir3_id
);
391 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RefreshEntry(dir_entry
));
393 EXPECT_EQ("drive/root/dir1/dir3/dir100",
394 resource_metadata_
->GetFilePath(dir_id
).AsUTF8Unsafe());
396 EXPECT_EQ(FILE_ERROR_OK
,
397 resource_metadata_
->GetResourceEntryById(dir_id
, &entry
));
398 EXPECT_EQ("dir100", entry
.base_name());
399 EXPECT_TRUE(entry
.file_info().is_directory());
400 EXPECT_EQ("id:dir2", entry
.resource_id());
402 // Make sure the children have moved over. Test file6.
404 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
405 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/dir100/file6"),
407 EXPECT_EQ("file6", entry
.base_name());
409 // Make sure dir2 no longer exists.
410 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
411 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry
));
413 // Make sure that directory cannot move under a file.
414 dir_entry
.set_parent_local_id(file_id
);
415 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY
,
416 resource_metadata_
->RefreshEntry(dir_entry
));
418 // Cannot refresh root.
420 dir_entry
.set_local_id(util::kDriveGrandRootLocalId
);
421 dir_entry
.set_title("new-root-name");
422 dir_entry
.set_parent_local_id(dir3_id
);
423 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION
,
424 resource_metadata_
->RefreshEntry(dir_entry
));
427 TEST_F(ResourceMetadataTest
, GetSubDirectoriesRecursively
) {
428 std::set
<base::FilePath
> sub_directories
;
430 // file9: not a directory, so no children.
431 std::string local_id
;
432 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
433 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &local_id
));
434 resource_metadata_
->GetSubDirectoriesRecursively(local_id
, &sub_directories
);
435 EXPECT_TRUE(sub_directories
.empty());
437 // dir2: no child directories.
438 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
439 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &local_id
));
440 resource_metadata_
->GetSubDirectoriesRecursively(local_id
, &sub_directories
);
441 EXPECT_TRUE(sub_directories
.empty());
442 const std::string dir2_id
= local_id
;
444 // dir1: dir3 is the only child
445 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
446 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id
));
447 resource_metadata_
->GetSubDirectoriesRecursively(local_id
, &sub_directories
);
448 EXPECT_EQ(1u, sub_directories
.size());
449 EXPECT_EQ(1u, sub_directories
.count(
450 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3")));
451 sub_directories
.clear();
453 // Add a few more directories to make sure deeper nesting works.
456 // dir2/dir101/dir102
457 // dir2/dir101/dir103
458 // dir2/dir101/dir104
459 // dir2/dir101/dir104/dir105
460 // dir2/dir101/dir104/dir105/dir106
461 // dir2/dir101/dir104/dir105/dir106/dir107
462 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
463 CreateDirectoryEntry("dir100", dir2_id
), &local_id
));
464 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
465 CreateDirectoryEntry("dir101", dir2_id
), &local_id
));
466 const std::string dir101_id
= local_id
;
467 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
468 CreateDirectoryEntry("dir102", dir101_id
), &local_id
));
469 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
470 CreateDirectoryEntry("dir103", dir101_id
), &local_id
));
471 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
472 CreateDirectoryEntry("dir104", dir101_id
), &local_id
));
473 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
474 CreateDirectoryEntry("dir105", local_id
), &local_id
));
475 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
476 CreateDirectoryEntry("dir106", local_id
), &local_id
));
477 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
478 CreateDirectoryEntry("dir107", local_id
), &local_id
));
480 resource_metadata_
->GetSubDirectoriesRecursively(dir2_id
, &sub_directories
);
481 EXPECT_EQ(8u, sub_directories
.size());
482 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
483 "drive/root/dir2/dir101")));
484 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
485 "drive/root/dir2/dir101/dir104")));
486 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
487 "drive/root/dir2/dir101/dir104/dir105/dir106/dir107")));
490 TEST_F(ResourceMetadataTest
, AddEntry
) {
491 base::FilePath drive_file_path
;
493 // Add a file to dir3.
494 std::string local_id
;
495 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
496 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &local_id
));
497 ResourceEntry file_entry
= CreateFileEntry("file100", local_id
);
498 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(file_entry
, &local_id
));
499 EXPECT_EQ("drive/root/dir1/dir3/file100",
500 resource_metadata_
->GetFilePath(local_id
).AsUTF8Unsafe());
503 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
504 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id
));
505 ResourceEntry dir_entry
= CreateDirectoryEntry("dir101", local_id
);
506 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(dir_entry
, &local_id
));
507 EXPECT_EQ("drive/root/dir1/dir101",
508 resource_metadata_
->GetFilePath(local_id
).AsUTF8Unsafe());
510 // Add to an invalid parent.
511 ResourceEntry file_entry3
= CreateFileEntry("file103", "id:invalid");
512 EXPECT_EQ(FILE_ERROR_NOT_FOUND
,
513 resource_metadata_
->AddEntry(file_entry3
, &local_id
));
515 // Add an existing file.
516 EXPECT_EQ(FILE_ERROR_EXISTS
,
517 resource_metadata_
->AddEntry(file_entry
, &local_id
));
520 TEST_F(ResourceMetadataTest
, RemoveEntry
) {
521 // Make sure file9 is found.
522 std::string file9_local_id
;
523 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
524 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"),
527 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
528 file9_local_id
, &entry
));
529 EXPECT_EQ("file9", entry
.base_name());
532 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RemoveEntry(file9_local_id
));
534 // file9 should no longer exist.
535 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
536 file9_local_id
, &entry
));
539 std::string dir3_local_id
;
540 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
541 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_local_id
));
542 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
543 dir3_local_id
, &entry
));
544 EXPECT_EQ("dir3", entry
.base_name());
547 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RemoveEntry(dir3_local_id
));
549 // dir3 should no longer exist.
550 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
551 dir3_local_id
, &entry
));
553 // Remove unknown local_id using RemoveEntry.
554 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->RemoveEntry("foo"));
556 // Try removing root. This should fail.
557 EXPECT_EQ(FILE_ERROR_ACCESS_DENIED
, resource_metadata_
->RemoveEntry(
558 util::kDriveGrandRootLocalId
));
561 TEST_F(ResourceMetadataTest
, GetResourceEntryById_RootDirectory
) {
562 // Look up the root directory by its ID.
564 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
565 util::kDriveGrandRootLocalId
, &entry
));
566 EXPECT_EQ("drive", entry
.base_name());
569 TEST_F(ResourceMetadataTest
, GetResourceEntryById
) {
570 // Get file4 by path.
571 std::string local_id
;
572 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
573 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &local_id
));
575 // Confirm that an existing file is found.
577 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
579 EXPECT_EQ("file4", entry
.base_name());
581 // Confirm that a non existing file is not found.
582 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
583 "file:non_existing", &entry
));
586 TEST_F(ResourceMetadataTest
, Iterate
) {
587 scoped_ptr
<ResourceMetadata::Iterator
> it
= resource_metadata_
->GetIterator();
590 int file_count
= 0, directory_count
= 0;
591 for (; !it
->IsAtEnd(); it
->Advance()) {
592 if (!it
->GetValue().file_info().is_directory())
598 EXPECT_EQ(7, file_count
);
599 EXPECT_EQ(7, directory_count
);
602 TEST_F(ResourceMetadataTest
, DuplicatedNames
) {
603 std::string root_local_id
;
604 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
605 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id
));
609 // When multiple entries with the same title are added in a single directory,
610 // their base_names are de-duped.
612 // - drive/root/foo (1)
613 std::string dir_id_0
;
614 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
615 CreateDirectoryEntryWithResourceId(
616 "foo", "foo0", root_local_id
), &dir_id_0
));
617 std::string dir_id_1
;
618 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
619 CreateDirectoryEntryWithResourceId(
620 "foo", "foo1", root_local_id
), &dir_id_1
));
622 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
624 EXPECT_EQ("foo", entry
.base_name());
625 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
627 EXPECT_EQ("foo (1)", entry
.base_name());
629 // - drive/root/foo/bar.txt
630 // - drive/root/foo/bar (1).txt
631 // - drive/root/foo/bar (2).txt
632 std::string file_id_0
;
633 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
634 CreateFileEntryWithResourceId(
635 "bar.txt", "bar0", dir_id_0
), &file_id_0
));
636 std::string file_id_1
;
637 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
638 CreateFileEntryWithResourceId(
639 "bar.txt", "bar1", dir_id_0
), &file_id_1
));
640 std::string file_id_2
;
641 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
642 CreateFileEntryWithResourceId(
643 "bar.txt", "bar2", dir_id_0
), &file_id_2
));
645 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
647 EXPECT_EQ("bar.txt", entry
.base_name());
648 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
650 EXPECT_EQ("bar (1).txt", entry
.base_name());
651 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
653 EXPECT_EQ("bar (2).txt", entry
.base_name());
655 // Same name but different parent. No renaming.
656 // - drive/root/foo (1)/bar.txt
657 std::string file_id_3
;
658 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
659 CreateFileEntryWithResourceId(
660 "bar.txt", "bar3", dir_id_1
), &file_id_3
));
662 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
664 EXPECT_EQ("bar.txt", entry
.base_name());
666 // Checks that the entries can be looked up by the de-duped paths.
667 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
668 base::FilePath::FromUTF8Unsafe("drive/root/foo/bar (2).txt"), &entry
));
669 EXPECT_EQ("bar2", entry
.resource_id());
670 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
671 base::FilePath::FromUTF8Unsafe("drive/root/foo (1)/bar.txt"), &entry
));
672 EXPECT_EQ("bar3", entry
.resource_id());
675 TEST_F(ResourceMetadataTest
, EncodedNames
) {
676 std::string root_local_id
;
677 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
678 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id
));
683 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
684 CreateDirectoryEntry("\\(^o^)/", root_local_id
), &dir_id
));
685 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
687 EXPECT_EQ("\\(^o^)_", entry
.base_name());
690 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
691 CreateFileEntryWithResourceId("Slash /.txt", "myfile", dir_id
),
693 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
695 EXPECT_EQ("Slash _.txt", entry
.base_name());
697 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
698 base::FilePath::FromUTF8Unsafe(
699 "drive/root/\\(^o^)_/Slash _.txt"),
701 EXPECT_EQ("myfile", entry
.resource_id());
704 TEST_F(ResourceMetadataTest
, Reset
) {
705 // The grand root has "root" which is not empty.
706 std::vector
<ResourceEntry
> entries
;
707 ASSERT_EQ(FILE_ERROR_OK
,
708 resource_metadata_
->ReadDirectoryByPath(
709 base::FilePath::FromUTF8Unsafe("drive/root"), &entries
));
710 ASSERT_FALSE(entries
.empty());
713 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->Reset());
715 // change stamp should be reset.
716 EXPECT_EQ(0, resource_metadata_
->GetLargestChangestamp());
718 // root should continue to exist.
720 ASSERT_EQ(FILE_ERROR_OK
,
721 resource_metadata_
->GetResourceEntryByPath(
722 base::FilePath::FromUTF8Unsafe("drive"), &entry
));
723 EXPECT_EQ("drive", entry
.base_name());
724 ASSERT_TRUE(entry
.file_info().is_directory());
725 EXPECT_EQ(util::kDriveGrandRootLocalId
, entry
.local_id());
727 // There are "other", "trash" and "root" under "drive".
728 ASSERT_EQ(FILE_ERROR_OK
,
729 resource_metadata_
->ReadDirectoryByPath(
730 base::FilePath::FromUTF8Unsafe("drive"), &entries
));
731 EXPECT_EQ(3U, entries
.size());
733 // The "other" directory should be empty.
734 ASSERT_EQ(FILE_ERROR_OK
,
735 resource_metadata_
->ReadDirectoryByPath(
736 base::FilePath::FromUTF8Unsafe("drive/other"), &entries
));
737 EXPECT_TRUE(entries
.empty());
739 // The "trash" directory should be empty.
740 ASSERT_EQ(FILE_ERROR_OK
,
741 resource_metadata_
->ReadDirectoryByPath(
742 base::FilePath::FromUTF8Unsafe("drive/trash"), &entries
));
743 EXPECT_TRUE(entries
.empty());
746 } // namespace internal