Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / resource_metadata_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/drive/resource_metadata.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
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/file_system_util.h"
15 #include "chrome/browser/chromeos/drive/test_util.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace drive {
20 namespace internal {
21 namespace {
22
23 // The changestamp of the resource metadata used in
24 // ResourceMetadataTest.
25 const int64 kTestChangestamp = 100;
26
27 // Returns the sorted base names from |entries|.
28 std::vector<std::string> GetSortedBaseNames(
29     const ResourceEntryVector& entries) {
30   std::vector<std::string> base_names;
31   for (size_t i = 0; i < entries.size(); ++i)
32     base_names.push_back(entries[i].base_name());
33   std::sort(base_names.begin(), base_names.end());
34
35   return base_names;
36 }
37
38 // Creates a ResourceEntry for a directory with explicitly set resource_id.
39 ResourceEntry CreateDirectoryEntryWithResourceId(
40     const std::string& title,
41     const std::string& resource_id,
42     const std::string& parent_local_id) {
43   ResourceEntry entry;
44   entry.set_title(title);
45   entry.set_resource_id(resource_id);
46   entry.set_parent_local_id(parent_local_id);
47   entry.mutable_file_info()->set_is_directory(true);
48   entry.mutable_directory_specific_info()->set_changestamp(kTestChangestamp);
49   return entry;
50 }
51
52 // Creates a ResourceEntry for a directory.
53 ResourceEntry CreateDirectoryEntry(const std::string& title,
54                                    const std::string& parent_local_id) {
55   return CreateDirectoryEntryWithResourceId(
56       title, "id:" + title, parent_local_id);
57 }
58
59 // Creates a ResourceEntry for a file with explicitly set resource_id.
60 ResourceEntry CreateFileEntryWithResourceId(
61     const std::string& title,
62     const std::string& resource_id,
63     const std::string& parent_local_id) {
64   ResourceEntry entry;
65   entry.set_title(title);
66   entry.set_resource_id(resource_id);
67   entry.set_parent_local_id(parent_local_id);
68   entry.mutable_file_info()->set_is_directory(false);
69   entry.mutable_file_info()->set_size(1024);
70   entry.mutable_file_specific_info()->set_md5("md5:" + title);
71   return entry;
72 }
73
74 // Creates a ResourceEntry for a file.
75 ResourceEntry CreateFileEntry(const std::string& title,
76                               const std::string& parent_local_id) {
77   return CreateFileEntryWithResourceId(title, "id:" + title, parent_local_id);
78 }
79
80 // Creates the following files/directories
81 // drive/root/dir1/
82 // drive/root/dir2/
83 // drive/root/dir1/dir3/
84 // drive/root/dir1/file4
85 // drive/root/dir1/file5
86 // drive/root/dir2/file6
87 // drive/root/dir2/file7
88 // drive/root/dir2/file8
89 // drive/root/dir1/dir3/file9
90 // drive/root/dir1/dir3/file10
91 void SetUpEntries(ResourceMetadata* resource_metadata) {
92   std::string local_id;
93   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->GetIdByPath(
94       util::GetDriveMyDriveRootPath(), &local_id));
95   const std::string root_local_id = local_id;
96
97   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
98       CreateDirectoryEntry("dir1", root_local_id), &local_id));
99   const std::string local_id_dir1 = local_id;
100
101   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
102       CreateDirectoryEntry("dir2", root_local_id), &local_id));
103   const std::string local_id_dir2 = local_id;
104
105   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
106       CreateDirectoryEntry("dir3", local_id_dir1), &local_id));
107   const std::string local_id_dir3 = local_id;
108
109   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
110       CreateFileEntry("file4", local_id_dir1), &local_id));
111   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
112       CreateFileEntry("file5", local_id_dir1), &local_id));
113
114   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
115       CreateFileEntry("file6", local_id_dir2), &local_id));
116   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
117       CreateFileEntry("file7", local_id_dir2), &local_id));
118   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
119       CreateFileEntry("file8", local_id_dir2), &local_id));
120
121   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
122       CreateFileEntry("file9", local_id_dir3), &local_id));
123   ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(
124       CreateFileEntry("file10", local_id_dir3), &local_id));
125
126   ASSERT_EQ(FILE_ERROR_OK,
127             resource_metadata->SetLargestChangestamp(kTestChangestamp));
128 }
129
130 }  // namespace
131
132 // Tests for methods running on the blocking task runner.
133 class ResourceMetadataTest : public testing::Test {
134  protected:
135   virtual void SetUp() OVERRIDE {
136     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
137
138     metadata_storage_.reset(new ResourceMetadataStorage(
139         temp_dir_.path(), base::MessageLoopProxy::current().get()));
140     ASSERT_TRUE(metadata_storage_->Initialize());
141
142     resource_metadata_.reset(new ResourceMetadata(
143         metadata_storage_.get(), base::MessageLoopProxy::current()));
144
145     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
146
147     SetUpEntries(resource_metadata_.get());
148   }
149
150   base::ScopedTempDir temp_dir_;
151   content::TestBrowserThreadBundle thread_bundle_;
152   scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests>
153       metadata_storage_;
154   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
155       resource_metadata_;
156 };
157
158 TEST_F(ResourceMetadataTest, LargestChangestamp) {
159   const int64 kChangestamp = 123456;
160   EXPECT_EQ(FILE_ERROR_OK,
161             resource_metadata_->SetLargestChangestamp(kChangestamp));
162   EXPECT_EQ(kChangestamp, resource_metadata_->GetLargestChangestamp());
163 }
164
165 TEST_F(ResourceMetadataTest, GetResourceEntryByPath) {
166   // Confirm that an existing file is found.
167   ResourceEntry entry;
168   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
169       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry));
170   EXPECT_EQ("file4", entry.base_name());
171
172   // Confirm that a non existing file is not found.
173   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath(
174       base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existing"), &entry));
175
176   // Confirm that the root is found.
177   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
178       base::FilePath::FromUTF8Unsafe("drive"), &entry));
179
180   // Confirm that a non existing file is not found at the root level.
181   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath(
182       base::FilePath::FromUTF8Unsafe("non_existing"), &entry));
183
184    // Confirm that an entry is not found with a wrong root.
185   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath(
186       base::FilePath::FromUTF8Unsafe("non_existing/root"), &entry));
187 }
188
189 TEST_F(ResourceMetadataTest, ReadDirectoryByPath) {
190   // Confirm that an existing directory is found.
191   ResourceEntryVector entries;
192   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->ReadDirectoryByPath(
193       base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entries));
194   ASSERT_EQ(3U, entries.size());
195   // The order is not guaranteed so we should sort the base names.
196   std::vector<std::string> base_names = GetSortedBaseNames(entries);
197   EXPECT_EQ("dir3", base_names[0]);
198   EXPECT_EQ("file4", base_names[1]);
199   EXPECT_EQ("file5", base_names[2]);
200
201   // Confirm that a non existing directory is not found.
202   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->ReadDirectoryByPath(
203       base::FilePath::FromUTF8Unsafe("drive/root/non_existing"), &entries));
204
205   // Confirm that reading a file results in FILE_ERROR_NOT_A_DIRECTORY.
206   EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, resource_metadata_->ReadDirectoryByPath(
207       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entries));
208 }
209
210 TEST_F(ResourceMetadataTest, RefreshEntry) {
211   base::FilePath drive_file_path;
212   ResourceEntry entry;
213
214   // Get file9.
215   std::string file_id;
216   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
217       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &file_id));
218   EXPECT_EQ(FILE_ERROR_OK,
219             resource_metadata_->GetResourceEntryById(file_id, &entry));
220   EXPECT_EQ("file9", entry.base_name());
221   EXPECT_TRUE(!entry.file_info().is_directory());
222   EXPECT_EQ("md5:file9", entry.file_specific_info().md5());
223
224   // Rename it.
225   ResourceEntry file_entry(entry);
226   file_entry.set_title("file100");
227   EXPECT_EQ(FILE_ERROR_OK,
228             resource_metadata_->RefreshEntry(file_entry));
229
230   EXPECT_EQ("drive/root/dir1/dir3/file100",
231             resource_metadata_->GetFilePath(file_id).AsUTF8Unsafe());
232   entry.Clear();
233   EXPECT_EQ(FILE_ERROR_OK,
234             resource_metadata_->GetResourceEntryById(file_id, &entry));
235   EXPECT_EQ("file100", entry.base_name());
236   EXPECT_TRUE(!entry.file_info().is_directory());
237   EXPECT_EQ("md5:file9", entry.file_specific_info().md5());
238
239   // Update the file md5.
240   const std::string updated_md5("md5:updated");
241   file_entry = entry;
242   file_entry.mutable_file_specific_info()->set_md5(updated_md5);
243   EXPECT_EQ(FILE_ERROR_OK,
244             resource_metadata_->RefreshEntry(file_entry));
245
246   EXPECT_EQ("drive/root/dir1/dir3/file100",
247             resource_metadata_->GetFilePath(file_id).AsUTF8Unsafe());
248   entry.Clear();
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(updated_md5, entry.file_specific_info().md5());
254
255   // Make sure we get the same thing from GetResourceEntryByPath.
256   entry.Clear();
257   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
258       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"), &entry));
259   EXPECT_EQ("file100", entry.base_name());
260   ASSERT_TRUE(!entry.file_info().is_directory());
261   EXPECT_EQ(updated_md5, entry.file_specific_info().md5());
262
263   // Get dir2.
264   entry.Clear();
265   std::string dir_id;
266   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
267       base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &dir_id));
268   EXPECT_EQ(FILE_ERROR_OK,
269             resource_metadata_->GetResourceEntryById(dir_id, &entry));
270   EXPECT_EQ("dir2", entry.base_name());
271   ASSERT_TRUE(entry.file_info().is_directory());
272
273   // Get dir3's ID.
274   std::string dir3_id;
275   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
276       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_id));
277
278   // Change the name to dir100 and change the parent to drive/dir1/dir3.
279   ResourceEntry dir_entry(entry);
280   dir_entry.set_title("dir100");
281   dir_entry.set_parent_local_id(dir3_id);
282   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(dir_entry));
283
284   EXPECT_EQ("drive/root/dir1/dir3/dir100",
285             resource_metadata_->GetFilePath(dir_id).AsUTF8Unsafe());
286   entry.Clear();
287   EXPECT_EQ(FILE_ERROR_OK,
288             resource_metadata_->GetResourceEntryById(dir_id, &entry));
289   EXPECT_EQ("dir100", entry.base_name());
290   EXPECT_TRUE(entry.file_info().is_directory());
291   EXPECT_EQ("id:dir2", entry.resource_id());
292
293   // Make sure the children have moved over. Test file6.
294   entry.Clear();
295   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
296       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/dir100/file6"),
297       &entry));
298   EXPECT_EQ("file6", entry.base_name());
299
300   // Make sure dir2 no longer exists.
301   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath(
302       base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry));
303
304   // Make sure that directory cannot move under a file.
305   dir_entry.set_parent_local_id(file_id);
306   EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY,
307             resource_metadata_->RefreshEntry(dir_entry));
308
309   // Cannot refresh root.
310   dir_entry.Clear();
311   dir_entry.set_local_id(util::kDriveGrandRootLocalId);
312   dir_entry.set_title("new-root-name");
313   dir_entry.set_parent_local_id(dir3_id);
314   EXPECT_EQ(FILE_ERROR_INVALID_OPERATION,
315             resource_metadata_->RefreshEntry(dir_entry));
316 }
317
318 TEST_F(ResourceMetadataTest, RefreshEntry_ResourceIDCheck) {
319   // Get an entry with a non-empty resource ID.
320   ResourceEntry entry;
321   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
322       base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entry));
323   EXPECT_FALSE(entry.resource_id().empty());
324
325   // Add a new entry with an empty resource ID.
326   ResourceEntry new_entry;
327   new_entry.set_parent_local_id(entry.local_id());
328   new_entry.set_title("new entry");
329   std::string local_id;
330   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(new_entry, &local_id));
331
332   // Try to refresh the new entry with a used resource ID.
333   new_entry.set_local_id(local_id);
334   new_entry.set_resource_id(entry.resource_id());
335   EXPECT_EQ(FILE_ERROR_INVALID_OPERATION,
336             resource_metadata_->RefreshEntry(new_entry));
337 }
338
339 TEST_F(ResourceMetadataTest, GetSubDirectoriesRecursively) {
340   std::set<base::FilePath> sub_directories;
341
342   // file9: not a directory, so no children.
343   std::string local_id;
344   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
345       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &local_id));
346   resource_metadata_->GetSubDirectoriesRecursively(local_id, &sub_directories);
347   EXPECT_TRUE(sub_directories.empty());
348
349   // dir2: no child directories.
350   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
351       base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &local_id));
352   resource_metadata_->GetSubDirectoriesRecursively(local_id, &sub_directories);
353   EXPECT_TRUE(sub_directories.empty());
354   const std::string dir2_id = local_id;
355
356   // dir1: dir3 is the only child
357   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
358       base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id));
359   resource_metadata_->GetSubDirectoriesRecursively(local_id, &sub_directories);
360   EXPECT_EQ(1u, sub_directories.size());
361   EXPECT_EQ(1u, sub_directories.count(
362       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3")));
363   sub_directories.clear();
364
365   // Add a few more directories to make sure deeper nesting works.
366   // dir2/dir100
367   // dir2/dir101
368   // dir2/dir101/dir102
369   // dir2/dir101/dir103
370   // dir2/dir101/dir104
371   // dir2/dir101/dir104/dir105
372   // dir2/dir101/dir104/dir105/dir106
373   // dir2/dir101/dir104/dir105/dir106/dir107
374   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
375       CreateDirectoryEntry("dir100", dir2_id), &local_id));
376   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
377       CreateDirectoryEntry("dir101", dir2_id), &local_id));
378   const std::string dir101_id = local_id;
379   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
380       CreateDirectoryEntry("dir102", dir101_id), &local_id));
381   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
382       CreateDirectoryEntry("dir103", dir101_id), &local_id));
383   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
384       CreateDirectoryEntry("dir104", dir101_id), &local_id));
385   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
386       CreateDirectoryEntry("dir105", local_id), &local_id));
387   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
388       CreateDirectoryEntry("dir106", local_id), &local_id));
389   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
390       CreateDirectoryEntry("dir107", local_id), &local_id));
391
392   resource_metadata_->GetSubDirectoriesRecursively(dir2_id, &sub_directories);
393   EXPECT_EQ(8u, sub_directories.size());
394   EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe(
395       "drive/root/dir2/dir101")));
396   EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe(
397       "drive/root/dir2/dir101/dir104")));
398   EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe(
399       "drive/root/dir2/dir101/dir104/dir105/dir106/dir107")));
400 }
401
402 TEST_F(ResourceMetadataTest, AddEntry) {
403   base::FilePath drive_file_path;
404
405   // Add a file to dir3.
406   std::string local_id;
407   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
408       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &local_id));
409   ResourceEntry file_entry = CreateFileEntry("file100", local_id);
410   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(file_entry, &local_id));
411   EXPECT_EQ("drive/root/dir1/dir3/file100",
412             resource_metadata_->GetFilePath(local_id).AsUTF8Unsafe());
413
414   // Add a directory.
415   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
416       base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id));
417   ResourceEntry dir_entry = CreateDirectoryEntry("dir101", local_id);
418   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(dir_entry, &local_id));
419   EXPECT_EQ("drive/root/dir1/dir101",
420             resource_metadata_->GetFilePath(local_id).AsUTF8Unsafe());
421
422   // Add to an invalid parent.
423   ResourceEntry file_entry3 = CreateFileEntry("file103", "id:invalid");
424   EXPECT_EQ(FILE_ERROR_NOT_FOUND,
425             resource_metadata_->AddEntry(file_entry3, &local_id));
426
427   // Add an existing file.
428   EXPECT_EQ(FILE_ERROR_EXISTS,
429             resource_metadata_->AddEntry(file_entry, &local_id));
430 }
431
432 TEST_F(ResourceMetadataTest, RemoveEntry) {
433   // Make sure file9 is found.
434   std::string file9_local_id;
435   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
436       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"),
437       &file9_local_id));
438   ResourceEntry entry;
439   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
440       file9_local_id, &entry));
441   EXPECT_EQ("file9", entry.base_name());
442
443   // Remove file9.
444   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(file9_local_id));
445
446   // file9 should no longer exist.
447   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
448       file9_local_id, &entry));
449
450   // Look for dir3.
451   std::string dir3_local_id;
452   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
453       base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_local_id));
454   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
455       dir3_local_id, &entry));
456   EXPECT_EQ("dir3", entry.base_name());
457
458   // Remove dir3.
459   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(dir3_local_id));
460
461   // dir3 should no longer exist.
462   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
463       dir3_local_id, &entry));
464
465   // Remove unknown local_id using RemoveEntry.
466   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->RemoveEntry("foo"));
467
468   // Try removing root. This should fail.
469   EXPECT_EQ(FILE_ERROR_ACCESS_DENIED, resource_metadata_->RemoveEntry(
470       util::kDriveGrandRootLocalId));
471 }
472
473 TEST_F(ResourceMetadataTest, GetResourceEntryById_RootDirectory) {
474   // Look up the root directory by its ID.
475   ResourceEntry entry;
476   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
477       util::kDriveGrandRootLocalId, &entry));
478   EXPECT_EQ("drive", entry.base_name());
479 }
480
481 TEST_F(ResourceMetadataTest, GetResourceEntryById) {
482   // Get file4 by path.
483   std::string local_id;
484   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
485       base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &local_id));
486
487   // Confirm that an existing file is found.
488   ResourceEntry entry;
489   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
490       local_id, &entry));
491   EXPECT_EQ("file4", entry.base_name());
492
493   // Confirm that a non existing file is not found.
494   EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById(
495       "file:non_existing", &entry));
496 }
497
498 TEST_F(ResourceMetadataTest, Iterate) {
499   scoped_ptr<ResourceMetadata::Iterator> it = resource_metadata_->GetIterator();
500   ASSERT_TRUE(it);
501
502   int file_count = 0, directory_count = 0;
503   for (; !it->IsAtEnd(); it->Advance()) {
504     if (!it->GetValue().file_info().is_directory())
505       ++file_count;
506     else
507       ++directory_count;
508   }
509
510   EXPECT_EQ(7, file_count);
511   EXPECT_EQ(7, directory_count);
512 }
513
514 TEST_F(ResourceMetadataTest, DuplicatedNames) {
515   std::string root_local_id;
516   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
517       base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id));
518
519   ResourceEntry entry;
520
521   // When multiple entries with the same title are added in a single directory,
522   // their base_names are de-duped.
523   // - drive/root/foo
524   // - drive/root/foo (1)
525   std::string dir_id_0;
526   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
527       CreateDirectoryEntryWithResourceId(
528           "foo", "foo0", root_local_id), &dir_id_0));
529   std::string dir_id_1;
530   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
531       CreateDirectoryEntryWithResourceId(
532           "foo", "foo1", root_local_id), &dir_id_1));
533
534   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
535       dir_id_0, &entry));
536   EXPECT_EQ("foo", entry.base_name());
537   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
538       dir_id_1, &entry));
539   EXPECT_EQ("foo (1)", entry.base_name());
540
541   // - drive/root/foo/bar.txt
542   // - drive/root/foo/bar (1).txt
543   // - drive/root/foo/bar (2).txt
544   // ...
545   // - drive/root/foo/bar (99).txt
546   std::vector<std::string> file_ids(100);
547   for (size_t i = 0; i < file_ids.size(); ++i) {
548     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
549         CreateFileEntryWithResourceId(
550             "bar.txt", base::StringPrintf("bar%d", static_cast<int>(i)),
551             dir_id_0), &file_ids[i]));
552   }
553
554   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
555       file_ids[0], &entry));
556   EXPECT_EQ("bar.txt", entry.base_name());
557   for (size_t i = 1; i < file_ids.size(); ++i) {
558     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
559         file_ids[i], &entry)) << i;
560     EXPECT_EQ(base::StringPrintf("bar (%d).txt", static_cast<int>(i)),
561               entry.base_name());
562   }
563
564   // Same name but different parent. No renaming.
565   // - drive/root/foo (1)/bar.txt
566   std::string file_id_3;
567   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
568       CreateFileEntryWithResourceId(
569           "bar.txt", "bar_different_parent", dir_id_1), &file_id_3));
570
571   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
572       file_id_3, &entry));
573   EXPECT_EQ("bar.txt", entry.base_name());
574
575   // Checks that the entries can be looked up by the de-duped paths.
576   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
577       base::FilePath::FromUTF8Unsafe("drive/root/foo/bar (2).txt"), &entry));
578   EXPECT_EQ("bar2", entry.resource_id());
579   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
580       base::FilePath::FromUTF8Unsafe("drive/root/foo (1)/bar.txt"), &entry));
581   EXPECT_EQ("bar_different_parent", entry.resource_id());
582 }
583
584 TEST_F(ResourceMetadataTest, EncodedNames) {
585   std::string root_local_id;
586   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
587       base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id));
588
589   ResourceEntry entry;
590
591   std::string dir_id;
592   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
593       CreateDirectoryEntry("\\(^o^)/", root_local_id), &dir_id));
594   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
595       dir_id, &entry));
596   EXPECT_EQ("\\(^o^)_", entry.base_name());
597
598   std::string file_id;
599   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
600       CreateFileEntryWithResourceId("Slash /.txt", "myfile", dir_id),
601       &file_id));
602   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById(
603       file_id, &entry));
604   EXPECT_EQ("Slash _.txt", entry.base_name());
605
606   ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath(
607       base::FilePath::FromUTF8Unsafe(
608           "drive/root/\\(^o^)_/Slash _.txt"),
609       &entry));
610   EXPECT_EQ("myfile", entry.resource_id());
611 }
612
613 TEST_F(ResourceMetadataTest, Reset) {
614   // The grand root has "root" which is not empty.
615   std::vector<ResourceEntry> entries;
616   ASSERT_EQ(FILE_ERROR_OK,
617             resource_metadata_->ReadDirectoryByPath(
618                 base::FilePath::FromUTF8Unsafe("drive/root"), &entries));
619   ASSERT_FALSE(entries.empty());
620
621   // Reset.
622   EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->Reset());
623
624   // change stamp should be reset.
625   EXPECT_EQ(0, resource_metadata_->GetLargestChangestamp());
626
627   // root should continue to exist.
628   ResourceEntry entry;
629   ASSERT_EQ(FILE_ERROR_OK,
630             resource_metadata_->GetResourceEntryByPath(
631                 base::FilePath::FromUTF8Unsafe("drive"), &entry));
632   EXPECT_EQ("drive", entry.base_name());
633   ASSERT_TRUE(entry.file_info().is_directory());
634   EXPECT_EQ(util::kDriveGrandRootLocalId, entry.local_id());
635
636   // There are "other", "trash" and "root" under "drive".
637   ASSERT_EQ(FILE_ERROR_OK,
638             resource_metadata_->ReadDirectoryByPath(
639                 base::FilePath::FromUTF8Unsafe("drive"), &entries));
640   EXPECT_EQ(3U, entries.size());
641
642   // The "other" directory should be empty.
643   ASSERT_EQ(FILE_ERROR_OK,
644             resource_metadata_->ReadDirectoryByPath(
645                 base::FilePath::FromUTF8Unsafe("drive/other"), &entries));
646   EXPECT_TRUE(entries.empty());
647
648   // The "trash" directory should be empty.
649   ASSERT_EQ(FILE_ERROR_OK,
650             resource_metadata_->ReadDirectoryByPath(
651                 base::FilePath::FromUTF8Unsafe("drive/trash"), &entries));
652   EXPECT_TRUE(entries.empty());
653 }
654
655 }  // namespace internal
656 }  // namespace drive