OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sync/api/attachments/attachment_store.h" | 5 #include "sync/api/attachments/attachment_store.h" |
6 | 6 |
7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
12 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
14 #include "sync/internal_api/attachments/attachment_store_test_template.h" | 14 #include "sync/internal_api/attachments/attachment_store_test_template.h" |
| 15 #include "sync/internal_api/attachments/proto/attachment_store.pb.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 18 #include "third_party/leveldatabase/src/include/leveldb/options.h" |
| 19 #include "third_party/leveldatabase/src/include/leveldb/slice.h" |
| 20 #include "third_party/leveldatabase/src/include/leveldb/status.h" |
16 | 21 |
17 namespace syncer { | 22 namespace syncer { |
18 | 23 |
19 namespace { | 24 namespace { |
20 | 25 |
21 void AttachmentStoreCreated(scoped_refptr<AttachmentStore>* store_dest, | 26 void AttachmentStoreCreated(scoped_refptr<AttachmentStore>* store_dest, |
22 AttachmentStore::Result* result_dest, | 27 AttachmentStore::Result* result_dest, |
23 const AttachmentStore::Result& result, | 28 const AttachmentStore::Result& result, |
24 const scoped_refptr<AttachmentStore>& store) { | 29 const scoped_refptr<AttachmentStore>& store) { |
25 *result_dest = result; | 30 *result_dest = result; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 } | 76 } |
72 | 77 |
73 void CopyResultAttachments( | 78 void CopyResultAttachments( |
74 AttachmentStore::Result* destination_result, | 79 AttachmentStore::Result* destination_result, |
75 const AttachmentStore::Result& source_result, | 80 const AttachmentStore::Result& source_result, |
76 scoped_ptr<AttachmentMap> source_attachments, | 81 scoped_ptr<AttachmentMap> source_attachments, |
77 scoped_ptr<AttachmentIdList> source_failed_attachment_ids) { | 82 scoped_ptr<AttachmentIdList> source_failed_attachment_ids) { |
78 CopyResult(destination_result, source_result); | 83 CopyResult(destination_result, source_result); |
79 } | 84 } |
80 | 85 |
| 86 scoped_ptr<leveldb::DB> OpenLevelDB(const base::FilePath& path) { |
| 87 leveldb::DB* db; |
| 88 leveldb::Options options; |
| 89 options.create_if_missing = true; |
| 90 leveldb::Status s = leveldb::DB::Open(options, path.AsUTF8Unsafe(), &db); |
| 91 EXPECT_TRUE(s.ok()); |
| 92 return make_scoped_ptr(db); |
| 93 } |
| 94 |
| 95 void UpdateStoreMetadataRecord(const base::FilePath& path, |
| 96 const std::string& content) { |
| 97 scoped_ptr<leveldb::DB> db = OpenLevelDB(path); |
| 98 leveldb::Status s = |
| 99 db->Put(leveldb::WriteOptions(), "database-metadata", content); |
| 100 EXPECT_TRUE(s.ok()); |
| 101 } |
| 102 |
| 103 std::string ReadStoreMetadataRecord(const base::FilePath& path) { |
| 104 scoped_ptr<leveldb::DB> db = OpenLevelDB(path); |
| 105 std::string content; |
| 106 leveldb::Status s = |
| 107 db->Get(leveldb::ReadOptions(), "database-metadata", &content); |
| 108 EXPECT_TRUE(s.ok()); |
| 109 return content; |
| 110 } |
| 111 |
81 void RunLoop() { | 112 void RunLoop() { |
82 base::RunLoop run_loop; | 113 base::RunLoop run_loop; |
83 run_loop.RunUntilIdle(); | 114 run_loop.RunUntilIdle(); |
84 } | 115 } |
85 }; | 116 }; |
86 | 117 |
87 // Ensure that store can be closed and reopen while retaining stored | 118 // Ensure that store can be closed and reopen while retaining stored |
88 // attachments. | 119 // attachments. |
89 TEST_F(OnDiskAttachmentStoreSpecificTest, CloseAndReopen) { | 120 TEST_F(OnDiskAttachmentStoreSpecificTest, CloseAndReopen) { |
90 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 121 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 EXPECT_EQ(result, AttachmentStore::SUCCESS); | 164 EXPECT_EQ(result, AttachmentStore::SUCCESS); |
134 } | 165 } |
135 | 166 |
136 // Ensure loading corrupt attachment store fails. | 167 // Ensure loading corrupt attachment store fails. |
137 TEST_F(OnDiskAttachmentStoreSpecificTest, FailToOpen) { | 168 TEST_F(OnDiskAttachmentStoreSpecificTest, FailToOpen) { |
138 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 169 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
139 base::FilePath db_path = | 170 base::FilePath db_path = |
140 temp_dir_.path().Append(FILE_PATH_LITERAL("leveldb")); | 171 temp_dir_.path().Append(FILE_PATH_LITERAL("leveldb")); |
141 base::CreateDirectory(db_path); | 172 base::CreateDirectory(db_path); |
142 | 173 |
143 // To simulate corrupt database write garbage to CURRENT file. | 174 // To simulate corrupt database write empty CURRENT file. |
144 std::string current_file_content = "abra.cadabra"; | 175 std::string current_file_content = ""; |
145 base::WriteFile(db_path.Append(FILE_PATH_LITERAL("CURRENT")), | 176 base::WriteFile(db_path.Append(FILE_PATH_LITERAL("CURRENT")), |
146 current_file_content.c_str(), | 177 current_file_content.c_str(), |
147 current_file_content.size()); | 178 current_file_content.size()); |
148 | 179 |
149 AttachmentStore::Result result = AttachmentStore::SUCCESS; | 180 AttachmentStore::Result result = AttachmentStore::SUCCESS; |
150 AttachmentStore::CreateOnDiskStore( | 181 AttachmentStore::CreateOnDiskStore( |
151 temp_dir_.path(), | 182 temp_dir_.path(), |
152 base::ThreadTaskRunnerHandle::Get(), | 183 base::ThreadTaskRunnerHandle::Get(), |
153 base::Bind(&AttachmentStoreCreated, &store_, &result)); | 184 base::Bind(&AttachmentStoreCreated, &store_, &result)); |
154 RunLoop(); | 185 RunLoop(); |
155 EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); | 186 EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); |
156 EXPECT_EQ(store_.get(), nullptr); | 187 EXPECT_EQ(store_.get(), nullptr); |
157 } | 188 } |
158 | 189 |
| 190 // Ensure that attachment store works correctly when store metadata is missing, |
| 191 // corrupt or has unknown schema version. |
| 192 TEST_F(OnDiskAttachmentStoreSpecificTest, StoreMetadata) { |
| 193 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 194 base::FilePath db_path = |
| 195 temp_dir_.path().Append(FILE_PATH_LITERAL("leveldb")); |
| 196 base::CreateDirectory(db_path); |
| 197 |
| 198 // Create and close empty database. |
| 199 OpenLevelDB(db_path); |
| 200 // Open database with AttachmentStore. |
| 201 AttachmentStore::Result result = AttachmentStore::UNSPECIFIED_ERROR; |
| 202 AttachmentStore::CreateOnDiskStore( |
| 203 temp_dir_.path(), |
| 204 base::ThreadTaskRunnerHandle::Get(), |
| 205 base::Bind(&AttachmentStoreCreated, &store_, &result)); |
| 206 RunLoop(); |
| 207 EXPECT_EQ(result, AttachmentStore::SUCCESS); |
| 208 // Close AttachmentStore so that test can check content. |
| 209 store_ = nullptr; |
| 210 RunLoop(); |
| 211 |
| 212 // AttachmentStore should create metadata record. |
| 213 std::string data = ReadStoreMetadataRecord(db_path); |
| 214 attachment_store_pb::AttachmentStoreMetadata metadata; |
| 215 EXPECT_TRUE(metadata.ParseFromString(data)); |
| 216 EXPECT_EQ(metadata.schema_version(), 1); |
| 217 |
| 218 // Set unknown future schema version. |
| 219 metadata.set_schema_version(2); |
| 220 data = metadata.SerializeAsString(); |
| 221 UpdateStoreMetadataRecord(db_path, data); |
| 222 |
| 223 // AttachmentStore should fail to load. |
| 224 result = AttachmentStore::SUCCESS; |
| 225 AttachmentStore::CreateOnDiskStore( |
| 226 temp_dir_.path(), |
| 227 base::ThreadTaskRunnerHandle::Get(), |
| 228 base::Bind(&AttachmentStoreCreated, &store_, &result)); |
| 229 RunLoop(); |
| 230 EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); |
| 231 EXPECT_EQ(store_.get(), nullptr); |
| 232 |
| 233 // Write garbage into metadata record. |
| 234 UpdateStoreMetadataRecord(db_path, "abra.cadabra"); |
| 235 |
| 236 // AttachmentStore should fail to load. |
| 237 result = AttachmentStore::SUCCESS; |
| 238 AttachmentStore::CreateOnDiskStore( |
| 239 temp_dir_.path(), |
| 240 base::ThreadTaskRunnerHandle::Get(), |
| 241 base::Bind(&AttachmentStoreCreated, &store_, &result)); |
| 242 RunLoop(); |
| 243 EXPECT_EQ(result, AttachmentStore::UNSPECIFIED_ERROR); |
| 244 EXPECT_EQ(store_.get(), nullptr); |
| 245 } |
| 246 |
159 } // namespace syncer | 247 } // namespace syncer |
OLD | NEW |