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/strings/stringprintf.h"
13 #include "chrome/browser/chromeos/drive/drive.pb.h"
14 #include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
15 #include "chrome/browser/chromeos/drive/file_cache.h"
16 #include "chrome/browser/chromeos/drive/file_system_util.h"
17 #include "chrome/browser/chromeos/drive/test_util.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "testing/gtest/include/gtest/gtest.h"
25 // The changestamp of the resource metadata used in
26 // ResourceMetadataTest.
27 const int64 kTestChangestamp
= 100;
29 // Returns the sorted base names from |entries|.
30 std::vector
<std::string
> GetSortedBaseNames(
31 const ResourceEntryVector
& entries
) {
32 std::vector
<std::string
> base_names
;
33 for (size_t i
= 0; i
< entries
.size(); ++i
)
34 base_names
.push_back(entries
[i
].base_name());
35 std::sort(base_names
.begin(), base_names
.end());
40 // Creates a ResourceEntry for a directory with explicitly set resource_id.
41 ResourceEntry
CreateDirectoryEntryWithResourceId(
42 const std::string
& title
,
43 const std::string
& resource_id
,
44 const std::string
& parent_local_id
) {
46 entry
.set_title(title
);
47 entry
.set_resource_id(resource_id
);
48 entry
.set_parent_local_id(parent_local_id
);
49 entry
.mutable_file_info()->set_is_directory(true);
50 entry
.mutable_directory_specific_info()->set_changestamp(kTestChangestamp
);
54 // Creates a ResourceEntry for a directory.
55 ResourceEntry
CreateDirectoryEntry(const std::string
& title
,
56 const std::string
& parent_local_id
) {
57 return CreateDirectoryEntryWithResourceId(
58 title
, "id:" + title
, parent_local_id
);
61 // Creates a ResourceEntry for a file with explicitly set resource_id.
62 ResourceEntry
CreateFileEntryWithResourceId(
63 const std::string
& title
,
64 const std::string
& resource_id
,
65 const std::string
& parent_local_id
) {
67 entry
.set_title(title
);
68 entry
.set_resource_id(resource_id
);
69 entry
.set_parent_local_id(parent_local_id
);
70 entry
.mutable_file_info()->set_is_directory(false);
71 entry
.mutable_file_info()->set_size(1024);
72 entry
.mutable_file_specific_info()->set_md5("md5:" + title
);
76 // Creates a ResourceEntry for a file.
77 ResourceEntry
CreateFileEntry(const std::string
& title
,
78 const std::string
& parent_local_id
) {
79 return CreateFileEntryWithResourceId(title
, "id:" + title
, parent_local_id
);
82 // Creates the following files/directories
85 // drive/root/dir1/dir3/
86 // drive/root/dir1/file4
87 // drive/root/dir1/file5
88 // drive/root/dir2/file6
89 // drive/root/dir2/file7
90 // drive/root/dir2/file8
91 // drive/root/dir1/dir3/file9
92 // drive/root/dir1/dir3/file10
93 void SetUpEntries(ResourceMetadata
* resource_metadata
) {
95 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->GetIdByPath(
96 util::GetDriveMyDriveRootPath(), &local_id
));
97 const std::string root_local_id
= local_id
;
99 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
100 CreateDirectoryEntry("dir1", root_local_id
), &local_id
));
101 const std::string local_id_dir1
= local_id
;
103 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
104 CreateDirectoryEntry("dir2", root_local_id
), &local_id
));
105 const std::string local_id_dir2
= local_id
;
107 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
108 CreateDirectoryEntry("dir3", local_id_dir1
), &local_id
));
109 const std::string local_id_dir3
= local_id
;
111 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
112 CreateFileEntry("file4", local_id_dir1
), &local_id
));
113 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
114 CreateFileEntry("file5", local_id_dir1
), &local_id
));
116 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
117 CreateFileEntry("file6", local_id_dir2
), &local_id
));
118 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
119 CreateFileEntry("file7", local_id_dir2
), &local_id
));
120 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
121 CreateFileEntry("file8", local_id_dir2
), &local_id
));
123 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
124 CreateFileEntry("file9", local_id_dir3
), &local_id
));
125 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata
->AddEntry(
126 CreateFileEntry("file10", local_id_dir3
), &local_id
));
128 ASSERT_EQ(FILE_ERROR_OK
,
129 resource_metadata
->SetLargestChangestamp(kTestChangestamp
));
134 // Tests for methods running on the blocking task runner.
135 class ResourceMetadataTest
: public testing::Test
{
137 void SetUp() override
{
138 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
140 metadata_storage_
.reset(new ResourceMetadataStorage(
141 temp_dir_
.path(), base::MessageLoopProxy::current().get()));
142 ASSERT_TRUE(metadata_storage_
->Initialize());
144 fake_free_disk_space_getter_
.reset(new FakeFreeDiskSpaceGetter
);
145 cache_
.reset(new FileCache(metadata_storage_
.get(),
147 base::MessageLoopProxy::current().get(),
148 fake_free_disk_space_getter_
.get()));
149 ASSERT_TRUE(cache_
->Initialize());
151 resource_metadata_
.reset(new ResourceMetadata(
152 metadata_storage_
.get(), cache_
.get(),
153 base::MessageLoopProxy::current()));
155 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->Initialize());
157 SetUpEntries(resource_metadata_
.get());
160 base::ScopedTempDir temp_dir_
;
161 content::TestBrowserThreadBundle thread_bundle_
;
162 scoped_ptr
<ResourceMetadataStorage
, test_util::DestroyHelperForTests
>
164 scoped_ptr
<FakeFreeDiskSpaceGetter
> fake_free_disk_space_getter_
;
165 scoped_ptr
<FileCache
, test_util::DestroyHelperForTests
> cache_
;
166 scoped_ptr
<ResourceMetadata
, test_util::DestroyHelperForTests
>
170 TEST_F(ResourceMetadataTest
, LargestChangestamp
) {
171 const int64 kChangestamp
= 123456;
172 EXPECT_EQ(FILE_ERROR_OK
,
173 resource_metadata_
->SetLargestChangestamp(kChangestamp
));
174 int64 changestamp
= 0;
175 EXPECT_EQ(FILE_ERROR_OK
,
176 resource_metadata_
->GetLargestChangestamp(&changestamp
));
177 EXPECT_EQ(kChangestamp
, changestamp
);
180 TEST_F(ResourceMetadataTest
, GetResourceEntryByPath
) {
181 // Confirm that an existing file is found.
183 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
184 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
185 EXPECT_EQ("file4", entry
.base_name());
187 // Confirm that a non existing file is not found.
188 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
189 base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existing"), &entry
));
191 // Confirm that the root is found.
192 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
193 base::FilePath::FromUTF8Unsafe("drive"), &entry
));
195 // Confirm that a non existing file is not found at the root level.
196 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
197 base::FilePath::FromUTF8Unsafe("non_existing"), &entry
));
199 // Confirm that an entry is not found with a wrong root.
200 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
201 base::FilePath::FromUTF8Unsafe("non_existing/root"), &entry
));
204 TEST_F(ResourceMetadataTest
, ReadDirectoryByPath
) {
205 // Confirm that an existing directory is found.
206 ResourceEntryVector entries
;
207 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->ReadDirectoryByPath(
208 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entries
));
209 ASSERT_EQ(3U, entries
.size());
210 // The order is not guaranteed so we should sort the base names.
211 std::vector
<std::string
> base_names
= GetSortedBaseNames(entries
);
212 EXPECT_EQ("dir3", base_names
[0]);
213 EXPECT_EQ("file4", base_names
[1]);
214 EXPECT_EQ("file5", base_names
[2]);
216 // Confirm that a non existing directory is not found.
217 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->ReadDirectoryByPath(
218 base::FilePath::FromUTF8Unsafe("drive/root/non_existing"), &entries
));
220 // Confirm that reading a file results in FILE_ERROR_NOT_A_DIRECTORY.
221 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY
, resource_metadata_
->ReadDirectoryByPath(
222 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entries
));
225 TEST_F(ResourceMetadataTest
, RefreshEntry
) {
226 base::FilePath drive_file_path
;
231 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
232 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &file_id
));
233 EXPECT_EQ(FILE_ERROR_OK
,
234 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
235 EXPECT_EQ("file9", entry
.base_name());
236 EXPECT_TRUE(!entry
.file_info().is_directory());
237 EXPECT_EQ("md5:file9", entry
.file_specific_info().md5());
240 ResourceEntry
file_entry(entry
);
241 file_entry
.set_title("file100");
242 EXPECT_EQ(FILE_ERROR_OK
,
243 resource_metadata_
->RefreshEntry(file_entry
));
246 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(file_id
, &path
));
247 EXPECT_EQ("drive/root/dir1/dir3/file100", path
.AsUTF8Unsafe());
249 EXPECT_EQ(FILE_ERROR_OK
,
250 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
251 EXPECT_EQ("file100", entry
.base_name());
252 EXPECT_TRUE(!entry
.file_info().is_directory());
253 EXPECT_EQ("md5:file9", entry
.file_specific_info().md5());
255 // Update the file md5.
256 const std::string
updated_md5("md5:updated");
258 file_entry
.mutable_file_specific_info()->set_md5(updated_md5
);
259 EXPECT_EQ(FILE_ERROR_OK
,
260 resource_metadata_
->RefreshEntry(file_entry
));
262 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(file_id
, &path
));
263 EXPECT_EQ("drive/root/dir1/dir3/file100", path
.AsUTF8Unsafe());
265 EXPECT_EQ(FILE_ERROR_OK
,
266 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
267 EXPECT_EQ("file100", entry
.base_name());
268 EXPECT_TRUE(!entry
.file_info().is_directory());
269 EXPECT_EQ(updated_md5
, entry
.file_specific_info().md5());
271 // Make sure we get the same thing from GetResourceEntryByPath.
273 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
274 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"), &entry
));
275 EXPECT_EQ("file100", entry
.base_name());
276 ASSERT_TRUE(!entry
.file_info().is_directory());
277 EXPECT_EQ(updated_md5
, entry
.file_specific_info().md5());
282 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
283 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &dir_id
));
284 EXPECT_EQ(FILE_ERROR_OK
,
285 resource_metadata_
->GetResourceEntryById(dir_id
, &entry
));
286 EXPECT_EQ("dir2", entry
.base_name());
287 ASSERT_TRUE(entry
.file_info().is_directory());
291 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
292 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_id
));
294 // Change the name to dir100 and change the parent to drive/dir1/dir3.
295 ResourceEntry
dir_entry(entry
);
296 dir_entry
.set_title("dir100");
297 dir_entry
.set_parent_local_id(dir3_id
);
298 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RefreshEntry(dir_entry
));
300 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(dir_id
, &path
));
301 EXPECT_EQ("drive/root/dir1/dir3/dir100", path
.AsUTF8Unsafe());
303 EXPECT_EQ(FILE_ERROR_OK
,
304 resource_metadata_
->GetResourceEntryById(dir_id
, &entry
));
305 EXPECT_EQ("dir100", entry
.base_name());
306 EXPECT_TRUE(entry
.file_info().is_directory());
307 EXPECT_EQ("id:dir2", entry
.resource_id());
309 // Make sure the children have moved over. Test file6.
311 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
312 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/dir100/file6"),
314 EXPECT_EQ("file6", entry
.base_name());
316 // Make sure dir2 no longer exists.
317 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
318 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry
));
320 // Make sure that directory cannot move under a file.
321 dir_entry
.set_parent_local_id(file_id
);
322 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY
,
323 resource_metadata_
->RefreshEntry(dir_entry
));
325 // Cannot refresh root.
327 dir_entry
.set_local_id(util::kDriveGrandRootLocalId
);
328 dir_entry
.set_title("new-root-name");
329 dir_entry
.set_parent_local_id(dir3_id
);
330 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION
,
331 resource_metadata_
->RefreshEntry(dir_entry
));
334 TEST_F(ResourceMetadataTest
, RefreshEntry_ResourceIDCheck
) {
335 // Get an entry with a non-empty resource ID.
337 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
338 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entry
));
339 EXPECT_FALSE(entry
.resource_id().empty());
341 // Add a new entry with an empty resource ID.
342 ResourceEntry new_entry
;
343 new_entry
.set_parent_local_id(entry
.local_id());
344 new_entry
.set_title("new entry");
345 std::string local_id
;
346 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(new_entry
, &local_id
));
348 // Try to refresh the new entry with a used resource ID.
349 new_entry
.set_local_id(local_id
);
350 new_entry
.set_resource_id(entry
.resource_id());
351 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION
,
352 resource_metadata_
->RefreshEntry(new_entry
));
355 TEST_F(ResourceMetadataTest
, RefreshEntry_DoNotOverwriteCacheState
) {
357 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
358 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
360 // Try to set MD5 with RefreshEntry.
361 entry
.mutable_file_specific_info()->mutable_cache_state()->set_md5("md5");
362 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RefreshEntry(entry
));
364 // Cache state is unchanged.
365 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
366 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
367 EXPECT_TRUE(entry
.file_specific_info().cache_state().md5().empty());
370 EXPECT_EQ(FILE_ERROR_OK
, cache_
->Pin(entry
.local_id()));
372 // Try to clear the cache state with RefreshEntry.
373 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
374 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
375 entry
.mutable_file_specific_info()->clear_cache_state();
376 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RefreshEntry(entry
));
378 // Cache state is not cleared.
379 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
380 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
381 EXPECT_TRUE(entry
.file_specific_info().cache_state().is_pinned());
384 TEST_F(ResourceMetadataTest
, GetSubDirectoriesRecursively
) {
385 std::set
<base::FilePath
> sub_directories
;
387 // file9: not a directory, so no children.
388 std::string local_id
;
389 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
390 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &local_id
));
391 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
392 local_id
, &sub_directories
));
393 EXPECT_TRUE(sub_directories
.empty());
395 // dir2: no child directories.
396 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
397 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &local_id
));
398 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
399 local_id
, &sub_directories
));
400 EXPECT_TRUE(sub_directories
.empty());
401 const std::string dir2_id
= local_id
;
403 // dir1: dir3 is the only child
404 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
405 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id
));
406 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
407 local_id
, &sub_directories
));
408 EXPECT_EQ(1u, sub_directories
.size());
409 EXPECT_EQ(1u, sub_directories
.count(
410 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3")));
411 sub_directories
.clear();
413 // Add a few more directories to make sure deeper nesting works.
416 // dir2/dir101/dir102
417 // dir2/dir101/dir103
418 // dir2/dir101/dir104
419 // dir2/dir101/dir104/dir105
420 // dir2/dir101/dir104/dir105/dir106
421 // dir2/dir101/dir104/dir105/dir106/dir107
422 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
423 CreateDirectoryEntry("dir100", dir2_id
), &local_id
));
424 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
425 CreateDirectoryEntry("dir101", dir2_id
), &local_id
));
426 const std::string dir101_id
= local_id
;
427 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
428 CreateDirectoryEntry("dir102", dir101_id
), &local_id
));
429 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
430 CreateDirectoryEntry("dir103", dir101_id
), &local_id
));
431 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
432 CreateDirectoryEntry("dir104", dir101_id
), &local_id
));
433 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
434 CreateDirectoryEntry("dir105", local_id
), &local_id
));
435 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
436 CreateDirectoryEntry("dir106", local_id
), &local_id
));
437 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
438 CreateDirectoryEntry("dir107", local_id
), &local_id
));
440 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
441 dir2_id
, &sub_directories
));
442 EXPECT_EQ(8u, sub_directories
.size());
443 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
444 "drive/root/dir2/dir101")));
445 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
446 "drive/root/dir2/dir101/dir104")));
447 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
448 "drive/root/dir2/dir101/dir104/dir105/dir106/dir107")));
451 TEST_F(ResourceMetadataTest
, AddEntry
) {
452 // Add a file to dir3.
453 std::string local_id
;
454 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
455 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &local_id
));
456 ResourceEntry file_entry
= CreateFileEntry("file100", local_id
);
457 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(file_entry
, &local_id
));
459 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(local_id
, &path
));
460 EXPECT_EQ("drive/root/dir1/dir3/file100", path
.AsUTF8Unsafe());
463 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
464 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id
));
465 ResourceEntry dir_entry
= CreateDirectoryEntry("dir101", local_id
);
466 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(dir_entry
, &local_id
));
467 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(local_id
, &path
));
468 EXPECT_EQ("drive/root/dir1/dir101", path
.AsUTF8Unsafe());
470 // Add to an invalid parent.
471 ResourceEntry file_entry3
= CreateFileEntry("file103", "id:invalid");
472 EXPECT_EQ(FILE_ERROR_NOT_FOUND
,
473 resource_metadata_
->AddEntry(file_entry3
, &local_id
));
475 // Add an existing file.
476 EXPECT_EQ(FILE_ERROR_EXISTS
,
477 resource_metadata_
->AddEntry(file_entry
, &local_id
));
480 TEST_F(ResourceMetadataTest
, RemoveEntry
) {
481 // Make sure file9 is found.
482 std::string file9_local_id
;
483 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
484 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"),
487 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
488 file9_local_id
, &entry
));
489 EXPECT_EQ("file9", entry
.base_name());
492 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RemoveEntry(file9_local_id
));
494 // file9 should no longer exist.
495 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
496 file9_local_id
, &entry
));
499 std::string dir3_local_id
;
500 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
501 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_local_id
));
502 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
503 dir3_local_id
, &entry
));
504 EXPECT_EQ("dir3", entry
.base_name());
507 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RemoveEntry(dir3_local_id
));
509 // dir3 should no longer exist.
510 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
511 dir3_local_id
, &entry
));
513 // Remove unknown local_id using RemoveEntry.
514 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->RemoveEntry("foo"));
516 // Try removing root. This should fail.
517 EXPECT_EQ(FILE_ERROR_ACCESS_DENIED
, resource_metadata_
->RemoveEntry(
518 util::kDriveGrandRootLocalId
));
521 TEST_F(ResourceMetadataTest
, GetResourceEntryById_RootDirectory
) {
522 // Look up the root directory by its ID.
524 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
525 util::kDriveGrandRootLocalId
, &entry
));
526 EXPECT_EQ("drive", entry
.base_name());
529 TEST_F(ResourceMetadataTest
, GetResourceEntryById
) {
530 // Get file4 by path.
531 std::string local_id
;
532 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
533 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &local_id
));
535 // Confirm that an existing file is found.
537 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
539 EXPECT_EQ("file4", entry
.base_name());
541 // Confirm that a non existing file is not found.
542 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
543 "non_existing", &entry
));
546 TEST_F(ResourceMetadataTest
, Iterate
) {
547 scoped_ptr
<ResourceMetadata::Iterator
> it
= resource_metadata_
->GetIterator();
550 int file_count
= 0, directory_count
= 0;
551 for (; !it
->IsAtEnd(); it
->Advance()) {
552 if (!it
->GetValue().file_info().is_directory())
558 EXPECT_EQ(7, file_count
);
559 EXPECT_EQ(7, directory_count
);
562 TEST_F(ResourceMetadataTest
, DuplicatedNames
) {
563 std::string root_local_id
;
564 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
565 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id
));
569 // When multiple entries with the same title are added in a single directory,
570 // their base_names are de-duped.
572 // - drive/root/foo (1)
573 std::string dir_id_0
;
574 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
575 CreateDirectoryEntryWithResourceId(
576 "foo", "foo0", root_local_id
), &dir_id_0
));
577 std::string dir_id_1
;
578 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
579 CreateDirectoryEntryWithResourceId(
580 "foo", "foo1", root_local_id
), &dir_id_1
));
582 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
584 EXPECT_EQ("foo", entry
.base_name());
585 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
587 EXPECT_EQ("foo (1)", entry
.base_name());
589 // - drive/root/foo/bar.txt
590 // - drive/root/foo/bar (1).txt
591 // - drive/root/foo/bar (2).txt
593 // - drive/root/foo/bar (99).txt
594 std::vector
<std::string
> file_ids(100);
595 for (size_t i
= 0; i
< file_ids
.size(); ++i
) {
596 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
597 CreateFileEntryWithResourceId(
598 "bar.txt", base::StringPrintf("bar%d", static_cast<int>(i
)),
599 dir_id_0
), &file_ids
[i
]));
602 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
603 file_ids
[0], &entry
));
604 EXPECT_EQ("bar.txt", entry
.base_name());
605 for (size_t i
= 1; i
< file_ids
.size(); ++i
) {
606 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
607 file_ids
[i
], &entry
)) << i
;
608 EXPECT_EQ(base::StringPrintf("bar (%d).txt", static_cast<int>(i
)),
612 // Same name but different parent. No renaming.
613 // - drive/root/foo (1)/bar.txt
614 std::string file_id_3
;
615 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
616 CreateFileEntryWithResourceId(
617 "bar.txt", "bar_different_parent", dir_id_1
), &file_id_3
));
619 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
621 EXPECT_EQ("bar.txt", entry
.base_name());
623 // Checks that the entries can be looked up by the de-duped paths.
624 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
625 base::FilePath::FromUTF8Unsafe("drive/root/foo/bar (2).txt"), &entry
));
626 EXPECT_EQ("bar2", entry
.resource_id());
627 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
628 base::FilePath::FromUTF8Unsafe("drive/root/foo (1)/bar.txt"), &entry
));
629 EXPECT_EQ("bar_different_parent", entry
.resource_id());
632 TEST_F(ResourceMetadataTest
, EncodedNames
) {
633 std::string root_local_id
;
634 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
635 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id
));
640 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
641 CreateDirectoryEntry("\\(^o^)/", root_local_id
), &dir_id
));
642 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
644 EXPECT_EQ("\\(^o^)_", entry
.base_name());
647 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
648 CreateFileEntryWithResourceId("Slash /.txt", "myfile", dir_id
),
650 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
652 EXPECT_EQ("Slash _.txt", entry
.base_name());
654 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
655 base::FilePath::FromUTF8Unsafe(
656 "drive/root/\\(^o^)_/Slash _.txt"),
658 EXPECT_EQ("myfile", entry
.resource_id());
661 TEST_F(ResourceMetadataTest
, Reset
) {
662 // The grand root has "root" which is not empty.
663 std::vector
<ResourceEntry
> entries
;
664 ASSERT_EQ(FILE_ERROR_OK
,
665 resource_metadata_
->ReadDirectoryByPath(
666 base::FilePath::FromUTF8Unsafe("drive/root"), &entries
));
667 ASSERT_FALSE(entries
.empty());
670 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->Reset());
672 // change stamp should be reset.
673 int64 changestamp
= 0;
674 EXPECT_EQ(FILE_ERROR_OK
,
675 resource_metadata_
->GetLargestChangestamp(&changestamp
));
676 EXPECT_EQ(0, changestamp
);
678 // root should continue to exist.
680 ASSERT_EQ(FILE_ERROR_OK
,
681 resource_metadata_
->GetResourceEntryByPath(
682 base::FilePath::FromUTF8Unsafe("drive"), &entry
));
683 EXPECT_EQ("drive", entry
.base_name());
684 ASSERT_TRUE(entry
.file_info().is_directory());
685 EXPECT_EQ(util::kDriveGrandRootLocalId
, entry
.local_id());
687 // There are "other", "trash" and "root" under "drive".
688 ASSERT_EQ(FILE_ERROR_OK
,
689 resource_metadata_
->ReadDirectoryByPath(
690 base::FilePath::FromUTF8Unsafe("drive"), &entries
));
691 EXPECT_EQ(3U, entries
.size());
693 // The "other" directory should be empty.
694 ASSERT_EQ(FILE_ERROR_OK
,
695 resource_metadata_
->ReadDirectoryByPath(
696 base::FilePath::FromUTF8Unsafe("drive/other"), &entries
));
697 EXPECT_TRUE(entries
.empty());
699 // The "trash" directory should be empty.
700 ASSERT_EQ(FILE_ERROR_OK
,
701 resource_metadata_
->ReadDirectoryByPath(
702 base::FilePath::FromUTF8Unsafe("drive/trash"), &entries
));
703 EXPECT_TRUE(entries
.empty());
706 } // namespace internal