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 "components/drive/resource_metadata.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/drive/drive.pb.h"
16 #include "components/drive/drive_test_util.h"
17 #include "components/drive/fake_free_disk_space_getter.h"
18 #include "components/drive/file_cache.h"
19 #include "components/drive/file_system_core_util.h"
20 #include "content/public/test/test_browser_thread_bundle.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 running on the blocking task runner.
137 class ResourceMetadataTest
: public testing::Test
{
139 void SetUp() override
{
140 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
142 metadata_storage_
.reset(new ResourceMetadataStorage(
143 temp_dir_
.path(), base::ThreadTaskRunnerHandle::Get().get()));
144 ASSERT_TRUE(metadata_storage_
->Initialize());
146 fake_free_disk_space_getter_
.reset(new FakeFreeDiskSpaceGetter
);
147 cache_
.reset(new FileCache(metadata_storage_
.get(),
149 base::ThreadTaskRunnerHandle::Get().get(),
150 fake_free_disk_space_getter_
.get()));
151 ASSERT_TRUE(cache_
->Initialize());
153 resource_metadata_
.reset(new ResourceMetadata(
154 metadata_storage_
.get(), cache_
.get(),
155 base::ThreadTaskRunnerHandle::Get()));
157 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->Initialize());
159 SetUpEntries(resource_metadata_
.get());
162 base::ScopedTempDir temp_dir_
;
163 content::TestBrowserThreadBundle thread_bundle_
;
164 scoped_ptr
<ResourceMetadataStorage
, test_util::DestroyHelperForTests
>
166 scoped_ptr
<FakeFreeDiskSpaceGetter
> fake_free_disk_space_getter_
;
167 scoped_ptr
<FileCache
, test_util::DestroyHelperForTests
> cache_
;
168 scoped_ptr
<ResourceMetadata
, test_util::DestroyHelperForTests
>
172 TEST_F(ResourceMetadataTest
, LargestChangestamp
) {
173 const int64 kChangestamp
= 123456;
174 EXPECT_EQ(FILE_ERROR_OK
,
175 resource_metadata_
->SetLargestChangestamp(kChangestamp
));
176 int64 changestamp
= 0;
177 EXPECT_EQ(FILE_ERROR_OK
,
178 resource_metadata_
->GetLargestChangestamp(&changestamp
));
179 EXPECT_EQ(kChangestamp
, changestamp
);
182 TEST_F(ResourceMetadataTest
, GetResourceEntryByPath
) {
183 // Confirm that an existing file is found.
185 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
186 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
187 EXPECT_EQ("file4", entry
.base_name());
189 // Confirm that a non existing file is not found.
190 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
191 base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existing"), &entry
));
193 // Confirm that the root is found.
194 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
195 base::FilePath::FromUTF8Unsafe("drive"), &entry
));
197 // Confirm that a non existing file is not found at the root level.
198 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
199 base::FilePath::FromUTF8Unsafe("non_existing"), &entry
));
201 // Confirm that an entry is not found with a wrong root.
202 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
203 base::FilePath::FromUTF8Unsafe("non_existing/root"), &entry
));
206 TEST_F(ResourceMetadataTest
, ReadDirectoryByPath
) {
207 // Confirm that an existing directory is found.
208 ResourceEntryVector entries
;
209 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->ReadDirectoryByPath(
210 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entries
));
211 ASSERT_EQ(3U, entries
.size());
212 // The order is not guaranteed so we should sort the base names.
213 std::vector
<std::string
> base_names
= GetSortedBaseNames(entries
);
214 EXPECT_EQ("dir3", base_names
[0]);
215 EXPECT_EQ("file4", base_names
[1]);
216 EXPECT_EQ("file5", base_names
[2]);
218 // Confirm that a non existing directory is not found.
219 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->ReadDirectoryByPath(
220 base::FilePath::FromUTF8Unsafe("drive/root/non_existing"), &entries
));
222 // Confirm that reading a file results in FILE_ERROR_NOT_A_DIRECTORY.
223 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY
, resource_metadata_
->ReadDirectoryByPath(
224 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entries
));
227 TEST_F(ResourceMetadataTest
, RefreshEntry
) {
228 base::FilePath drive_file_path
;
233 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
234 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &file_id
));
235 EXPECT_EQ(FILE_ERROR_OK
,
236 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
237 EXPECT_EQ("file9", entry
.base_name());
238 EXPECT_TRUE(!entry
.file_info().is_directory());
239 EXPECT_EQ("md5:file9", entry
.file_specific_info().md5());
242 ResourceEntry
file_entry(entry
);
243 file_entry
.set_title("file100");
244 EXPECT_EQ(FILE_ERROR_OK
,
245 resource_metadata_
->RefreshEntry(file_entry
));
248 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(file_id
, &path
));
249 EXPECT_EQ("drive/root/dir1/dir3/file100", path
.AsUTF8Unsafe());
251 EXPECT_EQ(FILE_ERROR_OK
,
252 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
253 EXPECT_EQ("file100", entry
.base_name());
254 EXPECT_TRUE(!entry
.file_info().is_directory());
255 EXPECT_EQ("md5:file9", entry
.file_specific_info().md5());
257 // Update the file md5.
258 const std::string
updated_md5("md5:updated");
260 file_entry
.mutable_file_specific_info()->set_md5(updated_md5
);
261 EXPECT_EQ(FILE_ERROR_OK
,
262 resource_metadata_
->RefreshEntry(file_entry
));
264 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(file_id
, &path
));
265 EXPECT_EQ("drive/root/dir1/dir3/file100", path
.AsUTF8Unsafe());
267 EXPECT_EQ(FILE_ERROR_OK
,
268 resource_metadata_
->GetResourceEntryById(file_id
, &entry
));
269 EXPECT_EQ("file100", entry
.base_name());
270 EXPECT_TRUE(!entry
.file_info().is_directory());
271 EXPECT_EQ(updated_md5
, entry
.file_specific_info().md5());
273 // Make sure we get the same thing from GetResourceEntryByPath.
275 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
276 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"), &entry
));
277 EXPECT_EQ("file100", entry
.base_name());
278 ASSERT_TRUE(!entry
.file_info().is_directory());
279 EXPECT_EQ(updated_md5
, entry
.file_specific_info().md5());
284 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
285 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &dir_id
));
286 EXPECT_EQ(FILE_ERROR_OK
,
287 resource_metadata_
->GetResourceEntryById(dir_id
, &entry
));
288 EXPECT_EQ("dir2", entry
.base_name());
289 ASSERT_TRUE(entry
.file_info().is_directory());
293 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
294 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_id
));
296 // Change the name to dir100 and change the parent to drive/dir1/dir3.
297 ResourceEntry
dir_entry(entry
);
298 dir_entry
.set_title("dir100");
299 dir_entry
.set_parent_local_id(dir3_id
);
300 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RefreshEntry(dir_entry
));
302 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(dir_id
, &path
));
303 EXPECT_EQ("drive/root/dir1/dir3/dir100", path
.AsUTF8Unsafe());
305 EXPECT_EQ(FILE_ERROR_OK
,
306 resource_metadata_
->GetResourceEntryById(dir_id
, &entry
));
307 EXPECT_EQ("dir100", entry
.base_name());
308 EXPECT_TRUE(entry
.file_info().is_directory());
309 EXPECT_EQ("id:dir2", entry
.resource_id());
311 // Make sure the children have moved over. Test file6.
313 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
314 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/dir100/file6"),
316 EXPECT_EQ("file6", entry
.base_name());
318 // Make sure dir2 no longer exists.
319 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryByPath(
320 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry
));
322 // Make sure that directory cannot move under a file.
323 dir_entry
.set_parent_local_id(file_id
);
324 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY
,
325 resource_metadata_
->RefreshEntry(dir_entry
));
327 // Cannot refresh root.
329 dir_entry
.set_local_id(util::kDriveGrandRootLocalId
);
330 dir_entry
.set_title("new-root-name");
331 dir_entry
.set_parent_local_id(dir3_id
);
332 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION
,
333 resource_metadata_
->RefreshEntry(dir_entry
));
336 TEST_F(ResourceMetadataTest
, RefreshEntry_ResourceIDCheck
) {
337 // Get an entry with a non-empty resource ID.
339 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
340 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entry
));
341 EXPECT_FALSE(entry
.resource_id().empty());
343 // Add a new entry with an empty resource ID.
344 ResourceEntry new_entry
;
345 new_entry
.set_parent_local_id(entry
.local_id());
346 new_entry
.set_title("new entry");
347 std::string local_id
;
348 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(new_entry
, &local_id
));
350 // Try to refresh the new entry with a used resource ID.
351 new_entry
.set_local_id(local_id
);
352 new_entry
.set_resource_id(entry
.resource_id());
353 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION
,
354 resource_metadata_
->RefreshEntry(new_entry
));
357 TEST_F(ResourceMetadataTest
, RefreshEntry_DoNotOverwriteCacheState
) {
359 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
360 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
362 // Try to set MD5 with RefreshEntry.
363 entry
.mutable_file_specific_info()->mutable_cache_state()->set_md5("md5");
364 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RefreshEntry(entry
));
366 // Cache state is unchanged.
367 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
368 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
369 EXPECT_TRUE(entry
.file_specific_info().cache_state().md5().empty());
372 EXPECT_EQ(FILE_ERROR_OK
, cache_
->Pin(entry
.local_id()));
374 // Try to clear the cache state with RefreshEntry.
375 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
376 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
377 entry
.mutable_file_specific_info()->clear_cache_state();
378 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RefreshEntry(entry
));
380 // Cache state is not cleared.
381 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
382 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry
));
383 EXPECT_TRUE(entry
.file_specific_info().cache_state().is_pinned());
386 TEST_F(ResourceMetadataTest
, GetSubDirectoriesRecursively
) {
387 std::set
<base::FilePath
> sub_directories
;
389 // file9: not a directory, so no children.
390 std::string local_id
;
391 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
392 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &local_id
));
393 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
394 local_id
, &sub_directories
));
395 EXPECT_TRUE(sub_directories
.empty());
397 // dir2: no child directories.
398 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
399 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &local_id
));
400 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
401 local_id
, &sub_directories
));
402 EXPECT_TRUE(sub_directories
.empty());
403 const std::string dir2_id
= local_id
;
405 // dir1: dir3 is the only child
406 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
407 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id
));
408 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
409 local_id
, &sub_directories
));
410 EXPECT_EQ(1u, sub_directories
.size());
411 EXPECT_EQ(1u, sub_directories
.count(
412 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3")));
413 sub_directories
.clear();
415 // Add a few more directories to make sure deeper nesting works.
418 // dir2/dir101/dir102
419 // dir2/dir101/dir103
420 // dir2/dir101/dir104
421 // dir2/dir101/dir104/dir105
422 // dir2/dir101/dir104/dir105/dir106
423 // dir2/dir101/dir104/dir105/dir106/dir107
424 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
425 CreateDirectoryEntry("dir100", dir2_id
), &local_id
));
426 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
427 CreateDirectoryEntry("dir101", dir2_id
), &local_id
));
428 const std::string dir101_id
= local_id
;
429 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
430 CreateDirectoryEntry("dir102", dir101_id
), &local_id
));
431 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
432 CreateDirectoryEntry("dir103", dir101_id
), &local_id
));
433 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
434 CreateDirectoryEntry("dir104", dir101_id
), &local_id
));
435 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
436 CreateDirectoryEntry("dir105", local_id
), &local_id
));
437 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
438 CreateDirectoryEntry("dir106", local_id
), &local_id
));
439 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
440 CreateDirectoryEntry("dir107", local_id
), &local_id
));
442 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetSubDirectoriesRecursively(
443 dir2_id
, &sub_directories
));
444 EXPECT_EQ(8u, sub_directories
.size());
445 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
446 "drive/root/dir2/dir101")));
447 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
448 "drive/root/dir2/dir101/dir104")));
449 EXPECT_EQ(1u, sub_directories
.count(base::FilePath::FromUTF8Unsafe(
450 "drive/root/dir2/dir101/dir104/dir105/dir106/dir107")));
453 TEST_F(ResourceMetadataTest
, AddEntry
) {
454 // Add a file to dir3.
455 std::string local_id
;
456 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
457 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &local_id
));
458 ResourceEntry file_entry
= CreateFileEntry("file100", local_id
);
459 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(file_entry
, &local_id
));
461 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(local_id
, &path
));
462 EXPECT_EQ("drive/root/dir1/dir3/file100", path
.AsUTF8Unsafe());
465 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
466 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id
));
467 ResourceEntry dir_entry
= CreateDirectoryEntry("dir101", local_id
);
468 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(dir_entry
, &local_id
));
469 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetFilePath(local_id
, &path
));
470 EXPECT_EQ("drive/root/dir1/dir101", path
.AsUTF8Unsafe());
472 // Add to an invalid parent.
473 ResourceEntry file_entry3
= CreateFileEntry("file103", "id:invalid");
474 EXPECT_EQ(FILE_ERROR_NOT_FOUND
,
475 resource_metadata_
->AddEntry(file_entry3
, &local_id
));
477 // Add an existing file.
478 EXPECT_EQ(FILE_ERROR_EXISTS
,
479 resource_metadata_
->AddEntry(file_entry
, &local_id
));
482 TEST_F(ResourceMetadataTest
, RemoveEntry
) {
483 // Make sure file9 is found.
484 std::string file9_local_id
;
485 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
486 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"),
489 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
490 file9_local_id
, &entry
));
491 EXPECT_EQ("file9", entry
.base_name());
494 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RemoveEntry(file9_local_id
));
496 // file9 should no longer exist.
497 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
498 file9_local_id
, &entry
));
501 std::string dir3_local_id
;
502 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
503 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_local_id
));
504 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
505 dir3_local_id
, &entry
));
506 EXPECT_EQ("dir3", entry
.base_name());
509 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->RemoveEntry(dir3_local_id
));
511 // dir3 should no longer exist.
512 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
513 dir3_local_id
, &entry
));
515 // Remove unknown local_id using RemoveEntry.
516 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->RemoveEntry("foo"));
518 // Try removing root. This should fail.
519 EXPECT_EQ(FILE_ERROR_ACCESS_DENIED
, resource_metadata_
->RemoveEntry(
520 util::kDriveGrandRootLocalId
));
523 TEST_F(ResourceMetadataTest
, GetResourceEntryById_RootDirectory
) {
524 // Look up the root directory by its ID.
526 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
527 util::kDriveGrandRootLocalId
, &entry
));
528 EXPECT_EQ("drive", entry
.base_name());
531 TEST_F(ResourceMetadataTest
, GetResourceEntryById
) {
532 // Get file4 by path.
533 std::string local_id
;
534 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
535 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &local_id
));
537 // Confirm that an existing file is found.
539 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
541 EXPECT_EQ("file4", entry
.base_name());
543 // Confirm that a non existing file is not found.
544 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, resource_metadata_
->GetResourceEntryById(
545 "non_existing", &entry
));
548 TEST_F(ResourceMetadataTest
, Iterate
) {
549 scoped_ptr
<ResourceMetadata::Iterator
> it
= resource_metadata_
->GetIterator();
552 int file_count
= 0, directory_count
= 0;
553 for (; !it
->IsAtEnd(); it
->Advance()) {
554 if (!it
->GetValue().file_info().is_directory())
560 EXPECT_EQ(7, file_count
);
561 EXPECT_EQ(7, directory_count
);
564 TEST_F(ResourceMetadataTest
, DuplicatedNames
) {
565 std::string root_local_id
;
566 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
567 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id
));
571 // When multiple entries with the same title are added in a single directory,
572 // their base_names are de-duped.
574 // - drive/root/foo (1)
575 std::string dir_id_0
;
576 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
577 CreateDirectoryEntryWithResourceId(
578 "foo", "foo0", root_local_id
), &dir_id_0
));
579 std::string dir_id_1
;
580 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
581 CreateDirectoryEntryWithResourceId(
582 "foo", "foo1", root_local_id
), &dir_id_1
));
584 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
586 EXPECT_EQ("foo", entry
.base_name());
587 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
589 EXPECT_EQ("foo (1)", entry
.base_name());
591 // - drive/root/foo/bar.txt
592 // - drive/root/foo/bar (1).txt
593 // - drive/root/foo/bar (2).txt
595 // - drive/root/foo/bar (99).txt
596 std::vector
<std::string
> file_ids(100);
597 for (size_t i
= 0; i
< file_ids
.size(); ++i
) {
598 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
599 CreateFileEntryWithResourceId(
600 "bar.txt", base::StringPrintf("bar%d", static_cast<int>(i
)),
601 dir_id_0
), &file_ids
[i
]));
604 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
605 file_ids
[0], &entry
));
606 EXPECT_EQ("bar.txt", entry
.base_name());
607 for (size_t i
= 1; i
< file_ids
.size(); ++i
) {
608 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
609 file_ids
[i
], &entry
)) << i
;
610 EXPECT_EQ(base::StringPrintf("bar (%d).txt", static_cast<int>(i
)),
614 // Same name but different parent. No renaming.
615 // - drive/root/foo (1)/bar.txt
616 std::string file_id_3
;
617 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
618 CreateFileEntryWithResourceId(
619 "bar.txt", "bar_different_parent", dir_id_1
), &file_id_3
));
621 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
623 EXPECT_EQ("bar.txt", entry
.base_name());
625 // Checks that the entries can be looked up by the de-duped paths.
626 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
627 base::FilePath::FromUTF8Unsafe("drive/root/foo/bar (2).txt"), &entry
));
628 EXPECT_EQ("bar2", entry
.resource_id());
629 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
630 base::FilePath::FromUTF8Unsafe("drive/root/foo (1)/bar.txt"), &entry
));
631 EXPECT_EQ("bar_different_parent", entry
.resource_id());
634 TEST_F(ResourceMetadataTest
, EncodedNames
) {
635 std::string root_local_id
;
636 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetIdByPath(
637 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id
));
642 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
643 CreateDirectoryEntry("\\(^o^)/", root_local_id
), &dir_id
));
644 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
646 EXPECT_EQ("\\(^o^)_", entry
.base_name());
649 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->AddEntry(
650 CreateFileEntryWithResourceId("Slash /.txt", "myfile", dir_id
),
652 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryById(
654 EXPECT_EQ("Slash _.txt", entry
.base_name());
656 ASSERT_EQ(FILE_ERROR_OK
, resource_metadata_
->GetResourceEntryByPath(
657 base::FilePath::FromUTF8Unsafe(
658 "drive/root/\\(^o^)_/Slash _.txt"),
660 EXPECT_EQ("myfile", entry
.resource_id());
663 TEST_F(ResourceMetadataTest
, Reset
) {
664 // The grand root has "root" which is not empty.
665 std::vector
<ResourceEntry
> entries
;
666 ASSERT_EQ(FILE_ERROR_OK
,
667 resource_metadata_
->ReadDirectoryByPath(
668 base::FilePath::FromUTF8Unsafe("drive/root"), &entries
));
669 ASSERT_FALSE(entries
.empty());
672 EXPECT_EQ(FILE_ERROR_OK
, resource_metadata_
->Reset());
674 // change stamp should be reset.
675 int64 changestamp
= 0;
676 EXPECT_EQ(FILE_ERROR_OK
,
677 resource_metadata_
->GetLargestChangestamp(&changestamp
));
678 EXPECT_EQ(0, changestamp
);
680 // root should continue to exist.
682 ASSERT_EQ(FILE_ERROR_OK
,
683 resource_metadata_
->GetResourceEntryByPath(
684 base::FilePath::FromUTF8Unsafe("drive"), &entry
));
685 EXPECT_EQ("drive", entry
.base_name());
686 ASSERT_TRUE(entry
.file_info().is_directory());
687 EXPECT_EQ(util::kDriveGrandRootLocalId
, entry
.local_id());
689 // There are "other", "trash" and "root" under "drive".
690 ASSERT_EQ(FILE_ERROR_OK
,
691 resource_metadata_
->ReadDirectoryByPath(
692 base::FilePath::FromUTF8Unsafe("drive"), &entries
));
693 EXPECT_EQ(3U, entries
.size());
695 // The "other" directory should be empty.
696 ASSERT_EQ(FILE_ERROR_OK
,
697 resource_metadata_
->ReadDirectoryByPath(
698 base::FilePath::FromUTF8Unsafe("drive/other"), &entries
));
699 EXPECT_TRUE(entries
.empty());
701 // The "trash" directory should be empty.
702 ASSERT_EQ(FILE_ERROR_OK
,
703 resource_metadata_
->ReadDirectoryByPath(
704 base::FilePath::FromUTF8Unsafe("drive/trash"), &entries
));
705 EXPECT_TRUE(entries
.empty());
708 } // namespace internal