Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / drive / resource_metadata_storage_unittest.cc
blob55969384d53994139e3320b47f03f557e4e6d15f
1 // Copyright 2013 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_storage.h"
7 #include <algorithm>
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/string_split.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "components/drive/drive.pb.h"
15 #include "components/drive/drive_test_util.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/leveldatabase/src/include/leveldb/db.h"
19 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
21 namespace drive {
22 namespace internal {
24 class ResourceMetadataStorageTest : public testing::Test {
25 protected:
26 void SetUp() override {
27 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
29 storage_.reset(new ResourceMetadataStorage(
30 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
31 ASSERT_TRUE(storage_->Initialize());
34 // Overwrites |storage_|'s version.
35 void SetDBVersion(int version) {
36 ResourceMetadataHeader header;
37 ASSERT_EQ(FILE_ERROR_OK, storage_->GetHeader(&header));
38 header.set_version(version);
39 EXPECT_EQ(FILE_ERROR_OK, storage_->PutHeader(header));
42 bool CheckValidity() {
43 return storage_->CheckValidity();
46 leveldb::DB* resource_map() { return storage_->resource_map_.get(); }
48 // Puts a child entry.
49 void PutChild(const std::string& parent_id,
50 const std::string& child_base_name,
51 const std::string& child_id) {
52 storage_->resource_map_->Put(
53 leveldb::WriteOptions(),
54 ResourceMetadataStorage::GetChildEntryKey(parent_id, child_base_name),
55 child_id);
58 // Removes a child entry.
59 void RemoveChild(const std::string& parent_id,
60 const std::string& child_base_name) {
61 storage_->resource_map_->Delete(
62 leveldb::WriteOptions(),
63 ResourceMetadataStorage::GetChildEntryKey(parent_id, child_base_name));
66 content::TestBrowserThreadBundle thread_bundle_;
67 base::ScopedTempDir temp_dir_;
68 scoped_ptr<ResourceMetadataStorage,
69 test_util::DestroyHelperForTests> storage_;
72 TEST_F(ResourceMetadataStorageTest, LargestChangestamp) {
73 const int64 kLargestChangestamp = 1234567890;
74 EXPECT_EQ(FILE_ERROR_OK,
75 storage_->SetLargestChangestamp(kLargestChangestamp));
76 int64 value = 0;
77 EXPECT_EQ(FILE_ERROR_OK, storage_->GetLargestChangestamp(&value));
78 EXPECT_EQ(kLargestChangestamp, value);
81 TEST_F(ResourceMetadataStorageTest, PutEntry) {
82 const std::string key1 = "abcdefg";
83 const std::string key2 = "abcd";
84 const std::string key3 = "efgh";
85 const std::string name2 = "ABCD";
86 const std::string name3 = "EFGH";
88 // key1 not found.
89 ResourceEntry result;
90 EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key1, &result));
92 // Put entry1.
93 ResourceEntry entry1;
94 entry1.set_local_id(key1);
95 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry1));
97 // key1 found.
98 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(key1, &result));
100 // key2 not found.
101 EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key2, &result));
103 // Put entry2 as a child of entry1.
104 ResourceEntry entry2;
105 entry2.set_local_id(key2);
106 entry2.set_parent_local_id(key1);
107 entry2.set_base_name(name2);
108 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry2));
110 // key2 found.
111 std::string child_id;
112 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(key2, &result));
113 EXPECT_EQ(FILE_ERROR_OK, storage_->GetChild(key1, name2, &child_id));
114 EXPECT_EQ(key2, child_id);
116 // Put entry3 as a child of entry2.
117 ResourceEntry entry3;
118 entry3.set_local_id(key3);
119 entry3.set_parent_local_id(key2);
120 entry3.set_base_name(name3);
121 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry3));
123 // key3 found.
124 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(key3, &result));
125 EXPECT_EQ(FILE_ERROR_OK, storage_->GetChild(key2, name3, &child_id));
126 EXPECT_EQ(key3, child_id);
128 // Change entry3's parent to entry1.
129 entry3.set_parent_local_id(key1);
130 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry3));
132 // entry3 is a child of entry1 now.
133 EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetChild(key2, name3, &child_id));
134 EXPECT_EQ(FILE_ERROR_OK, storage_->GetChild(key1, name3, &child_id));
135 EXPECT_EQ(key3, child_id);
137 // Remove entries.
138 EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key3));
139 EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key3, &result));
140 EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key2));
141 EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key2, &result));
142 EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key1));
143 EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key1, &result));
146 TEST_F(ResourceMetadataStorageTest, Iterator) {
147 // Prepare data.
148 std::vector<std::string> keys;
150 keys.push_back("entry1");
151 keys.push_back("entry2");
152 keys.push_back("entry3");
153 keys.push_back("entry4");
155 for (size_t i = 0; i < keys.size(); ++i) {
156 ResourceEntry entry;
157 entry.set_local_id(keys[i]);
158 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
161 // Iterate and check the result.
162 std::map<std::string, ResourceEntry> found_entries;
163 scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator();
164 ASSERT_TRUE(it);
165 for (; !it->IsAtEnd(); it->Advance()) {
166 const ResourceEntry& entry = it->GetValue();
167 found_entries[it->GetID()] = entry;
169 EXPECT_FALSE(it->HasError());
171 EXPECT_EQ(keys.size(), found_entries.size());
172 for (size_t i = 0; i < keys.size(); ++i)
173 EXPECT_EQ(1U, found_entries.count(keys[i]));
176 TEST_F(ResourceMetadataStorageTest, GetIdByResourceId) {
177 const std::string local_id = "local_id";
178 const std::string resource_id = "resource_id";
180 // Resource ID to local ID mapping is not stored yet.
181 std::string id;
182 EXPECT_EQ(FILE_ERROR_NOT_FOUND,
183 storage_->GetIdByResourceId(resource_id, &id));
185 // Put an entry with the resource ID.
186 ResourceEntry entry;
187 entry.set_local_id(local_id);
188 entry.set_resource_id(resource_id);
189 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
191 // Can get local ID by resource ID.
192 EXPECT_EQ(FILE_ERROR_OK, storage_->GetIdByResourceId(resource_id, &id));
193 EXPECT_EQ(local_id, id);
195 // Resource ID to local ID mapping is removed.
196 EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(local_id));
197 EXPECT_EQ(FILE_ERROR_NOT_FOUND,
198 storage_->GetIdByResourceId(resource_id, &id));
201 TEST_F(ResourceMetadataStorageTest, GetChildren) {
202 const std::string parents_id[] = { "mercury", "venus", "mars", "jupiter",
203 "saturn" };
204 std::vector<base::StringPairs> children_name_id(arraysize(parents_id));
205 // Skip children_name_id[0/1] here because Mercury and Venus have no moon.
206 children_name_id[2].push_back(std::make_pair("phobos", "mars_i"));
207 children_name_id[2].push_back(std::make_pair("deimos", "mars_ii"));
208 children_name_id[3].push_back(std::make_pair("io", "jupiter_i"));
209 children_name_id[3].push_back(std::make_pair("europa", "jupiter_ii"));
210 children_name_id[3].push_back(std::make_pair("ganymede", "jupiter_iii"));
211 children_name_id[3].push_back(std::make_pair("calisto", "jupiter_iv"));
212 children_name_id[4].push_back(std::make_pair("mimas", "saturn_i"));
213 children_name_id[4].push_back(std::make_pair("enceladus", "saturn_ii"));
214 children_name_id[4].push_back(std::make_pair("tethys", "saturn_iii"));
215 children_name_id[4].push_back(std::make_pair("dione", "saturn_iv"));
216 children_name_id[4].push_back(std::make_pair("rhea", "saturn_v"));
217 children_name_id[4].push_back(std::make_pair("titan", "saturn_vi"));
218 children_name_id[4].push_back(std::make_pair("iapetus", "saturn_vii"));
220 // Put parents.
221 for (size_t i = 0; i < arraysize(parents_id); ++i) {
222 ResourceEntry entry;
223 entry.set_local_id(parents_id[i]);
224 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
227 // Put children.
228 for (size_t i = 0; i < children_name_id.size(); ++i) {
229 for (size_t j = 0; j < children_name_id[i].size(); ++j) {
230 ResourceEntry entry;
231 entry.set_local_id(children_name_id[i][j].second);
232 entry.set_parent_local_id(parents_id[i]);
233 entry.set_base_name(children_name_id[i][j].first);
234 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
238 // Try to get children.
239 for (size_t i = 0; i < children_name_id.size(); ++i) {
240 std::vector<std::string> children;
241 storage_->GetChildren(parents_id[i], &children);
242 EXPECT_EQ(children_name_id[i].size(), children.size());
243 for (size_t j = 0; j < children_name_id[i].size(); ++j) {
244 EXPECT_EQ(1, std::count(children.begin(),
245 children.end(),
246 children_name_id[i][j].second));
251 TEST_F(ResourceMetadataStorageTest, OpenExistingDB) {
252 const std::string parent_id1 = "abcdefg";
253 const std::string child_name1 = "WXYZABC";
254 const std::string child_id1 = "qwerty";
256 ResourceEntry entry1;
257 entry1.set_local_id(parent_id1);
258 ResourceEntry entry2;
259 entry2.set_local_id(child_id1);
260 entry2.set_parent_local_id(parent_id1);
261 entry2.set_base_name(child_name1);
263 // Put some data.
264 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry1));
265 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry2));
267 // Close DB and reopen.
268 storage_.reset(new ResourceMetadataStorage(
269 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
270 ASSERT_TRUE(storage_->Initialize());
272 // Can read data.
273 ResourceEntry result;
274 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(parent_id1, &result));
276 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(child_id1, &result));
277 EXPECT_EQ(parent_id1, result.parent_local_id());
278 EXPECT_EQ(child_name1, result.base_name());
280 std::string child_id;
281 EXPECT_EQ(FILE_ERROR_OK,
282 storage_->GetChild(parent_id1, child_name1, &child_id));
283 EXPECT_EQ(child_id1, child_id);
286 TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M29) {
287 const int64 kLargestChangestamp = 1234567890;
288 const std::string title = "title";
290 // Construct M29 version DB.
291 SetDBVersion(6);
292 EXPECT_EQ(FILE_ERROR_OK,
293 storage_->SetLargestChangestamp(kLargestChangestamp));
295 leveldb::WriteBatch batch;
297 // Put a file entry and its cache entry.
298 ResourceEntry entry;
299 std::string serialized_entry;
300 entry.set_title(title);
301 entry.set_resource_id("file:abcd");
302 EXPECT_TRUE(entry.SerializeToString(&serialized_entry));
303 batch.Put("file:abcd", serialized_entry);
305 FileCacheEntry cache_entry;
306 EXPECT_TRUE(cache_entry.SerializeToString(&serialized_entry));
307 batch.Put(std::string("file:abcd") + '\0' + "CACHE", serialized_entry);
309 EXPECT_TRUE(resource_map()->Write(leveldb::WriteOptions(), &batch).ok());
311 // Upgrade and reopen.
312 storage_.reset();
313 EXPECT_TRUE(ResourceMetadataStorage::UpgradeOldDB(temp_dir_.path()));
314 storage_.reset(new ResourceMetadataStorage(
315 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
316 ASSERT_TRUE(storage_->Initialize());
318 // Resource-ID-to-local-ID mapping is added.
319 std::string id;
320 EXPECT_EQ(FILE_ERROR_OK,
321 storage_->GetIdByResourceId("abcd", &id)); // "file:" is dropped.
323 // Data is erased, except cache entries.
324 int64 largest_changestamp = 0;
325 EXPECT_EQ(FILE_ERROR_OK,
326 storage_->GetLargestChangestamp(&largest_changestamp));
327 EXPECT_EQ(0, largest_changestamp);
328 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(id, &entry));
329 EXPECT_TRUE(entry.title().empty());
330 EXPECT_TRUE(entry.file_specific_info().has_cache_state());
333 TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M32) {
334 const int64 kLargestChangestamp = 1234567890;
335 const std::string title = "title";
336 const std::string resource_id = "abcd";
337 const std::string local_id = "local-abcd";
339 // Construct M32 version DB.
340 SetDBVersion(11);
341 EXPECT_EQ(FILE_ERROR_OK,
342 storage_->SetLargestChangestamp(kLargestChangestamp));
344 leveldb::WriteBatch batch;
346 // Put a file entry and its cache and id entry.
347 ResourceEntry entry;
348 std::string serialized_entry;
349 entry.set_title(title);
350 entry.set_local_id(local_id);
351 entry.set_resource_id(resource_id);
352 EXPECT_TRUE(entry.SerializeToString(&serialized_entry));
353 batch.Put(local_id, serialized_entry);
355 FileCacheEntry cache_entry;
356 EXPECT_TRUE(cache_entry.SerializeToString(&serialized_entry));
357 batch.Put(local_id + '\0' + "CACHE", serialized_entry);
359 batch.Put('\0' + std::string("ID") + '\0' + resource_id, local_id);
361 EXPECT_TRUE(resource_map()->Write(leveldb::WriteOptions(), &batch).ok());
363 // Upgrade and reopen.
364 storage_.reset();
365 EXPECT_TRUE(ResourceMetadataStorage::UpgradeOldDB(temp_dir_.path()));
366 storage_.reset(new ResourceMetadataStorage(
367 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
368 ASSERT_TRUE(storage_->Initialize());
370 // Data is erased, except cache and id mapping entries.
371 std::string id;
372 EXPECT_EQ(FILE_ERROR_OK, storage_->GetIdByResourceId(resource_id, &id));
373 EXPECT_EQ(local_id, id);
374 int64 largest_changestamp = 0;
375 EXPECT_EQ(FILE_ERROR_OK,
376 storage_->GetLargestChangestamp(&largest_changestamp));
377 EXPECT_EQ(0, largest_changestamp);
378 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(id, &entry));
379 EXPECT_TRUE(entry.title().empty());
380 EXPECT_TRUE(entry.file_specific_info().has_cache_state());
383 TEST_F(ResourceMetadataStorageTest, IncompatibleDB_M33) {
384 const int64 kLargestChangestamp = 1234567890;
385 const std::string title = "title";
386 const std::string resource_id = "abcd";
387 const std::string local_id = "local-abcd";
388 const std::string md5 = "md5";
389 const std::string resource_id2 = "efgh";
390 const std::string local_id2 = "local-efgh";
391 const std::string md5_2 = "md5_2";
393 // Construct M33 version DB.
394 SetDBVersion(12);
395 EXPECT_EQ(FILE_ERROR_OK,
396 storage_->SetLargestChangestamp(kLargestChangestamp));
398 leveldb::WriteBatch batch;
400 // Put a file entry and its cache and id entry.
401 ResourceEntry entry;
402 std::string serialized_entry;
403 entry.set_title(title);
404 entry.set_local_id(local_id);
405 entry.set_resource_id(resource_id);
406 EXPECT_TRUE(entry.SerializeToString(&serialized_entry));
407 batch.Put(local_id, serialized_entry);
409 FileCacheEntry cache_entry;
410 cache_entry.set_md5(md5);
411 EXPECT_TRUE(cache_entry.SerializeToString(&serialized_entry));
412 batch.Put(local_id + '\0' + "CACHE", serialized_entry);
414 batch.Put('\0' + std::string("ID") + '\0' + resource_id, local_id);
416 // Put another cache entry which is not accompanied by a ResourceEntry.
417 cache_entry.set_md5(md5_2);
418 EXPECT_TRUE(cache_entry.SerializeToString(&serialized_entry));
419 batch.Put(local_id2 + '\0' + "CACHE", serialized_entry);
420 batch.Put('\0' + std::string("ID") + '\0' + resource_id2, local_id2);
422 EXPECT_TRUE(resource_map()->Write(leveldb::WriteOptions(), &batch).ok());
424 // Upgrade and reopen.
425 storage_.reset();
426 EXPECT_TRUE(ResourceMetadataStorage::UpgradeOldDB(temp_dir_.path()));
427 storage_.reset(new ResourceMetadataStorage(
428 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
429 ASSERT_TRUE(storage_->Initialize());
431 // No data is lost.
432 int64 largest_changestamp = 0;
433 EXPECT_EQ(FILE_ERROR_OK,
434 storage_->GetLargestChangestamp(&largest_changestamp));
435 EXPECT_EQ(kLargestChangestamp, largest_changestamp);
437 std::string id;
438 EXPECT_EQ(FILE_ERROR_OK, storage_->GetIdByResourceId(resource_id, &id));
439 EXPECT_EQ(local_id, id);
440 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(id, &entry));
441 EXPECT_EQ(title, entry.title());
442 EXPECT_EQ(md5, entry.file_specific_info().cache_state().md5());
444 EXPECT_EQ(FILE_ERROR_OK, storage_->GetIdByResourceId(resource_id2, &id));
445 EXPECT_EQ(local_id2, id);
446 EXPECT_EQ(FILE_ERROR_OK, storage_->GetEntry(id, &entry));
447 EXPECT_EQ(md5_2, entry.file_specific_info().cache_state().md5());
450 TEST_F(ResourceMetadataStorageTest, IncompatibleDB_Unknown) {
451 const int64 kLargestChangestamp = 1234567890;
452 const std::string key1 = "abcd";
454 // Put some data.
455 EXPECT_EQ(FILE_ERROR_OK,
456 storage_->SetLargestChangestamp(kLargestChangestamp));
457 ResourceEntry entry;
458 entry.set_local_id(key1);
459 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
461 // Set newer version, upgrade and reopen DB.
462 SetDBVersion(ResourceMetadataStorage::kDBVersion + 1);
463 storage_.reset();
464 EXPECT_FALSE(ResourceMetadataStorage::UpgradeOldDB(temp_dir_.path()));
465 storage_.reset(new ResourceMetadataStorage(
466 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
467 ASSERT_TRUE(storage_->Initialize());
469 // Data is erased because of the incompatible version.
470 int64 largest_changestamp = 0;
471 EXPECT_EQ(FILE_ERROR_OK,
472 storage_->GetLargestChangestamp(&largest_changestamp));
473 EXPECT_EQ(0, largest_changestamp);
474 EXPECT_EQ(FILE_ERROR_NOT_FOUND, storage_->GetEntry(key1, &entry));
477 TEST_F(ResourceMetadataStorageTest, DeleteUnusedIDEntries) {
478 leveldb::WriteBatch batch;
480 // Put an ID entry with a corresponding ResourceEntry.
481 ResourceEntry entry;
482 entry.set_local_id("id1");
483 entry.set_resource_id("resource_id1");
485 std::string serialized_entry;
486 EXPECT_TRUE(entry.SerializeToString(&serialized_entry));
487 batch.Put("id1", serialized_entry);
488 batch.Put('\0' + std::string("ID") + '\0' + "resource_id1", "id1");
490 // Put an ID entry without any corresponding entries.
491 batch.Put('\0' + std::string("ID") + '\0' + "resource_id2", "id3");
493 EXPECT_TRUE(resource_map()->Write(leveldb::WriteOptions(), &batch).ok());
495 // Upgrade and reopen.
496 storage_.reset();
497 EXPECT_TRUE(ResourceMetadataStorage::UpgradeOldDB(temp_dir_.path()));
498 storage_.reset(new ResourceMetadataStorage(
499 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
500 ASSERT_TRUE(storage_->Initialize());
502 // Only the unused entry is deleted.
503 std::string id;
504 EXPECT_EQ(FILE_ERROR_OK, storage_->GetIdByResourceId("resource_id1", &id));
505 EXPECT_EQ("id1", id);
506 EXPECT_EQ(FILE_ERROR_NOT_FOUND,
507 storage_->GetIdByResourceId("resource_id2", &id));
510 TEST_F(ResourceMetadataStorageTest, WrongPath) {
511 // Create a file.
512 base::FilePath path;
513 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &path));
515 storage_.reset(new ResourceMetadataStorage(
516 path, base::ThreadTaskRunnerHandle::Get().get()));
517 // Cannot initialize DB beacause the path does not point a directory.
518 ASSERT_FALSE(storage_->Initialize());
521 TEST_F(ResourceMetadataStorageTest, RecoverCacheEntriesFromTrashedResourceMap) {
522 // Put entry with id_foo.
523 ResourceEntry entry;
524 entry.set_local_id("id_foo");
525 entry.set_base_name("foo");
526 entry.set_title("foo");
527 entry.mutable_file_specific_info()->mutable_cache_state()->set_md5("md5_foo");
528 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
530 // Put entry with id_bar as a id_foo's child.
531 entry.set_local_id("id_bar");
532 entry.set_parent_local_id("id_foo");
533 entry.set_base_name("bar");
534 entry.set_title("bar");
535 entry.mutable_file_specific_info()->mutable_cache_state()->set_md5("md5_bar");
536 entry.mutable_file_specific_info()->mutable_cache_state()->set_is_dirty(true);
537 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
539 // Remove parent-child relationship to make the DB invalid.
540 RemoveChild("id_foo", "bar");
541 EXPECT_FALSE(CheckValidity());
543 // Reopen. This should result in trashing the DB.
544 storage_.reset(new ResourceMetadataStorage(
545 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get()));
546 ASSERT_TRUE(storage_->Initialize());
548 // Recover cache entries from the trashed DB.
549 ResourceMetadataStorage::RecoveredCacheInfoMap recovered_cache_info;
550 storage_->RecoverCacheInfoFromTrashedResourceMap(&recovered_cache_info);
551 EXPECT_EQ(2U, recovered_cache_info.size());
552 EXPECT_FALSE(recovered_cache_info["id_foo"].is_dirty);
553 EXPECT_EQ("md5_foo", recovered_cache_info["id_foo"].md5);
554 EXPECT_EQ("foo", recovered_cache_info["id_foo"].title);
555 EXPECT_TRUE(recovered_cache_info["id_bar"].is_dirty);
556 EXPECT_EQ("md5_bar", recovered_cache_info["id_bar"].md5);
557 EXPECT_EQ("bar", recovered_cache_info["id_bar"].title);
560 TEST_F(ResourceMetadataStorageTest, CheckValidity) {
561 const std::string key1 = "foo";
562 const std::string name1 = "hoge";
563 const std::string key2 = "bar";
564 const std::string name2 = "fuga";
565 const std::string key3 = "boo";
566 const std::string name3 = "piyo";
568 // Empty storage is valid.
569 EXPECT_TRUE(CheckValidity());
571 // Put entry with key1.
572 ResourceEntry entry;
573 entry.set_local_id(key1);
574 entry.set_base_name(name1);
575 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
576 EXPECT_TRUE(CheckValidity());
578 // Put entry with key2 under key1.
579 entry.set_local_id(key2);
580 entry.set_parent_local_id(key1);
581 entry.set_base_name(name2);
582 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
583 EXPECT_TRUE(CheckValidity());
585 RemoveChild(key1, name2);
586 EXPECT_FALSE(CheckValidity()); // Missing parent-child relationship.
588 // Add back parent-child relationship between key1 and key2.
589 PutChild(key1, name2, key2);
590 EXPECT_TRUE(CheckValidity());
592 // Add parent-child relationship between key2 and key3.
593 PutChild(key2, name3, key3);
594 EXPECT_FALSE(CheckValidity()); // key3 is not stored in the storage.
596 // Put entry with key3 under key2.
597 entry.set_local_id(key3);
598 entry.set_parent_local_id(key2);
599 entry.set_base_name(name3);
600 EXPECT_EQ(FILE_ERROR_OK, storage_->PutEntry(entry));
601 EXPECT_TRUE(CheckValidity());
603 // Parent-child relationship with wrong name.
604 RemoveChild(key2, name3);
605 EXPECT_FALSE(CheckValidity());
606 PutChild(key2, name2, key3);
607 EXPECT_FALSE(CheckValidity());
609 // Fix up the relationship between key2 and key3.
610 RemoveChild(key2, name2);
611 EXPECT_FALSE(CheckValidity());
612 PutChild(key2, name3, key3);
613 EXPECT_TRUE(CheckValidity());
615 // Remove key2.
616 RemoveChild(key1, name2);
617 EXPECT_FALSE(CheckValidity());
618 EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key2));
619 EXPECT_FALSE(CheckValidity());
621 // Remove key3.
622 RemoveChild(key2, name3);
623 EXPECT_FALSE(CheckValidity());
624 EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key3));
625 EXPECT_TRUE(CheckValidity());
627 // Remove key1.
628 EXPECT_EQ(FILE_ERROR_OK, storage_->RemoveEntry(key1));
629 EXPECT_TRUE(CheckValidity());
632 } // namespace internal
633 } // namespace drive