Remove the domain check gating settings protection.
[chromium-blink-merge.git] / components / leveldb_proto / proto_database_impl_unittest.cc
blob512045222811a01bfdd62f742b72d92f6755bcc0
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
3 // found in the LICENSE file.
5 #include "components/leveldb_proto/proto_database_impl.h"
7 #include <map>
9 #include "base/bind.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/run_loop.h"
13 #include "base/threading/thread.h"
14 #include "components/leveldb_proto/leveldb_database.h"
15 #include "components/leveldb_proto/testing/proto/test.pb.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using base::MessageLoop;
20 using base::ScopedTempDir;
21 using testing::Invoke;
22 using testing::Return;
23 using testing::_;
25 namespace leveldb_proto {
27 namespace {
29 typedef std::map<std::string, TestProto> EntryMap;
31 class MockDB : public LevelDB {
32 public:
33 MOCK_METHOD1(Init, bool(const base::FilePath&));
34 MOCK_METHOD2(Save, bool(const KeyValueVector&, const KeyVector&));
35 MOCK_METHOD1(Load, bool(std::vector<std::string>*));
37 MockDB() {
38 ON_CALL(*this, Init(_)).WillByDefault(Return(true));
39 ON_CALL(*this, Save(_, _)).WillByDefault(Return(true));
40 ON_CALL(*this, Load(_)).WillByDefault(Return(true));
44 class MockDatabaseCaller {
45 public:
46 MOCK_METHOD1(InitCallback, void(bool));
47 MOCK_METHOD1(SaveCallback, void(bool));
48 void LoadCallback(bool success, scoped_ptr<std::vector<TestProto> > entries) {
49 LoadCallback1(success, entries.get());
51 MOCK_METHOD2(LoadCallback1, void(bool, std::vector<TestProto>*));
54 } // namespace
56 EntryMap GetSmallModel() {
57 EntryMap model;
59 model["0"].set_id("0");
60 model["0"].set_data("http://foo.com/1");
62 model["1"].set_id("1");
63 model["1"].set_data("http://bar.com/all");
65 model["2"].set_id("2");
66 model["2"].set_data("http://baz.com/1");
68 return model;
71 void ExpectEntryPointersEquals(EntryMap expected,
72 const std::vector<TestProto>& actual) {
73 EXPECT_EQ(expected.size(), actual.size());
74 for (size_t i = 0; i < actual.size(); i++) {
75 EntryMap::iterator expected_it = expected.find(actual[i].id());
76 EXPECT_TRUE(expected_it != expected.end());
77 std::string serialized_expected = expected_it->second.SerializeAsString();
78 std::string serialized_actual = actual[i].SerializeAsString();
79 EXPECT_EQ(serialized_expected, serialized_actual);
80 expected.erase(expected_it);
84 class ProtoDatabaseImplTest : public testing::Test {
85 public:
86 virtual void SetUp() {
87 main_loop_.reset(new MessageLoop());
88 db_.reset(
89 new ProtoDatabaseImpl<TestProto>(main_loop_->message_loop_proxy()));
92 virtual void TearDown() {
93 db_.reset();
94 base::RunLoop().RunUntilIdle();
95 main_loop_.reset();
98 scoped_ptr<ProtoDatabaseImpl<TestProto> > db_;
99 scoped_ptr<MessageLoop> main_loop_;
102 // Test that ProtoDatabaseImpl calls Init on the underlying database and that
103 // the caller's InitCallback is called with the correct value.
104 TEST_F(ProtoDatabaseImplTest, TestDBInitSuccess) {
105 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
107 MockDB* mock_db = new MockDB();
108 EXPECT_CALL(*mock_db, Init(path)).WillOnce(Return(true));
110 MockDatabaseCaller caller;
111 EXPECT_CALL(caller, InitCallback(true));
113 db_->InitWithDatabase(
114 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
115 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
117 base::RunLoop().RunUntilIdle();
120 TEST_F(ProtoDatabaseImplTest, TestDBInitFailure) {
121 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
123 MockDB* mock_db = new MockDB();
124 EXPECT_CALL(*mock_db, Init(path)).WillOnce(Return(false));
126 MockDatabaseCaller caller;
127 EXPECT_CALL(caller, InitCallback(false));
129 db_->InitWithDatabase(
130 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
131 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
133 base::RunLoop().RunUntilIdle();
136 ACTION_P(AppendLoadEntries, model) {
137 std::vector<std::string>* output = arg0;
138 for (EntryMap::const_iterator it = model.begin(); it != model.end(); ++it) {
139 output->push_back(it->second.SerializeAsString());
141 return true;
144 ACTION_P(VerifyLoadEntries, expected) {
145 std::vector<TestProto>* actual = arg1;
146 ExpectEntryPointersEquals(expected, *actual);
149 // Test that ProtoDatabaseImpl calls Load on the underlying database and that
150 // the caller's LoadCallback is called with the correct success value. Also
151 // confirms that on success, the expected entries are passed to the caller's
152 // LoadCallback.
153 TEST_F(ProtoDatabaseImplTest, TestDBLoadSuccess) {
154 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
156 MockDB* mock_db = new MockDB();
157 MockDatabaseCaller caller;
158 EntryMap model = GetSmallModel();
160 EXPECT_CALL(*mock_db, Init(_));
161 EXPECT_CALL(caller, InitCallback(_));
162 db_->InitWithDatabase(
163 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
164 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
166 EXPECT_CALL(*mock_db, Load(_)).WillOnce(AppendLoadEntries(model));
167 EXPECT_CALL(caller, LoadCallback1(true, _))
168 .WillOnce(VerifyLoadEntries(testing::ByRef(model)));
169 db_->LoadEntries(
170 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller)));
172 base::RunLoop().RunUntilIdle();
175 TEST_F(ProtoDatabaseImplTest, TestDBLoadFailure) {
176 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
178 MockDB* mock_db = new MockDB();
179 MockDatabaseCaller caller;
181 EXPECT_CALL(*mock_db, Init(_));
182 EXPECT_CALL(caller, InitCallback(_));
183 db_->InitWithDatabase(
184 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
185 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
187 EXPECT_CALL(*mock_db, Load(_)).WillOnce(Return(false));
188 EXPECT_CALL(caller, LoadCallback1(false, _));
189 db_->LoadEntries(
190 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller)));
192 base::RunLoop().RunUntilIdle();
195 ACTION_P(VerifyUpdateEntries, expected) {
196 const KeyValueVector actual = arg0;
197 // Create a vector of TestProto from |actual| to reuse the comparison
198 // function.
199 std::vector<TestProto> extracted_entries;
200 for (KeyValueVector::const_iterator it = actual.begin(); it != actual.end();
201 ++it) {
202 TestProto entry;
203 entry.ParseFromString(it->second);
204 extracted_entries.push_back(entry);
206 ExpectEntryPointersEquals(expected, extracted_entries);
207 return true;
210 // Test that ProtoDatabaseImpl calls Save on the underlying database with the
211 // correct entries to save and that the caller's SaveCallback is called with the
212 // correct success value.
213 TEST_F(ProtoDatabaseImplTest, TestDBSaveSuccess) {
214 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
216 MockDB* mock_db = new MockDB();
217 MockDatabaseCaller caller;
218 EntryMap model = GetSmallModel();
220 EXPECT_CALL(*mock_db, Init(_));
221 EXPECT_CALL(caller, InitCallback(_));
222 db_->InitWithDatabase(
223 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
224 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
226 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
227 new ProtoDatabase<TestProto>::KeyEntryVector());
228 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) {
229 entries->push_back(std::make_pair(it->second.id(), it->second));
231 scoped_ptr<KeyVector> keys_to_remove(new KeyVector());
233 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(VerifyUpdateEntries(model));
234 EXPECT_CALL(caller, SaveCallback(true));
235 db_->UpdateEntries(
236 entries.Pass(), keys_to_remove.Pass(),
237 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
239 base::RunLoop().RunUntilIdle();
242 TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) {
243 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
245 MockDB* mock_db = new MockDB();
246 MockDatabaseCaller caller;
247 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
248 new ProtoDatabase<TestProto>::KeyEntryVector());
249 scoped_ptr<KeyVector> keys_to_remove(new KeyVector());
251 EXPECT_CALL(*mock_db, Init(_));
252 EXPECT_CALL(caller, InitCallback(_));
253 db_->InitWithDatabase(
254 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
255 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
257 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false));
258 EXPECT_CALL(caller, SaveCallback(false));
259 db_->UpdateEntries(
260 entries.Pass(), keys_to_remove.Pass(),
261 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
263 base::RunLoop().RunUntilIdle();
266 // Test that ProtoDatabaseImpl calls Save on the underlying database with the
267 // correct entries to delete and that the caller's SaveCallback is called with
268 // the correct success value.
269 TEST_F(ProtoDatabaseImplTest, TestDBRemoveSuccess) {
270 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
272 MockDB* mock_db = new MockDB();
273 MockDatabaseCaller caller;
274 EntryMap model = GetSmallModel();
276 EXPECT_CALL(*mock_db, Init(_));
277 EXPECT_CALL(caller, InitCallback(_));
278 db_->InitWithDatabase(
279 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
280 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
282 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
283 new ProtoDatabase<TestProto>::KeyEntryVector());
284 scoped_ptr<KeyVector> keys_to_remove(new KeyVector());
285 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) {
286 keys_to_remove->push_back(it->second.id());
289 KeyVector keys_copy(*keys_to_remove.get());
290 EXPECT_CALL(*mock_db, Save(_, keys_copy)).WillOnce(Return(true));
291 EXPECT_CALL(caller, SaveCallback(true));
292 db_->UpdateEntries(
293 entries.Pass(), keys_to_remove.Pass(),
294 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
296 base::RunLoop().RunUntilIdle();
299 TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) {
300 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
302 MockDB* mock_db = new MockDB();
303 MockDatabaseCaller caller;
304 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
305 new ProtoDatabase<TestProto>::KeyEntryVector());
306 scoped_ptr<KeyVector> keys_to_remove(new KeyVector());
308 EXPECT_CALL(*mock_db, Init(_));
309 EXPECT_CALL(caller, InitCallback(_));
310 db_->InitWithDatabase(
311 scoped_ptr<LevelDB>(mock_db), base::FilePath(path),
312 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
314 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false));
315 EXPECT_CALL(caller, SaveCallback(false));
316 db_->UpdateEntries(
317 entries.Pass(), keys_to_remove.Pass(),
318 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
320 base::RunLoop().RunUntilIdle();
323 // This tests that normal usage of the real database does not cause any
324 // threading violations.
325 TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) {
326 base::MessageLoop main_loop;
328 ScopedTempDir temp_dir;
329 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
331 base::Thread db_thread("dbthread");
332 ASSERT_TRUE(db_thread.Start());
334 scoped_ptr<ProtoDatabaseImpl<TestProto> > db(
335 new ProtoDatabaseImpl<TestProto>(db_thread.message_loop_proxy()));
337 MockDatabaseCaller caller;
338 EXPECT_CALL(caller, InitCallback(_));
339 db->Init(temp_dir.path(), base::Bind(&MockDatabaseCaller::InitCallback,
340 base::Unretained(&caller)));
342 db.reset();
344 base::RunLoop run_loop;
345 db_thread.message_loop_proxy()->PostTaskAndReply(
346 FROM_HERE, base::Bind(base::DoNothing), run_loop.QuitClosure());
347 run_loop.Run();
350 // Test that the LevelDB properly saves entries and that load returns the saved
351 // entries. If |close_after_save| is true, the database will be closed after
352 // saving and then re-opened to ensure that the data is properly persisted.
353 void TestLevelDBSaveAndLoad(bool close_after_save) {
354 ScopedTempDir temp_dir;
355 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
357 EntryMap model = GetSmallModel();
359 KeyValueVector save_entries;
360 std::vector<std::string> load_entries;
361 KeyVector remove_keys;
363 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) {
364 save_entries.push_back(
365 std::make_pair(it->second.id(), it->second.SerializeAsString()));
368 scoped_ptr<LevelDB> db(new LevelDB());
369 EXPECT_TRUE(db->Init(temp_dir.path()));
370 EXPECT_TRUE(db->Save(save_entries, remove_keys));
372 if (close_after_save) {
373 db.reset(new LevelDB());
374 EXPECT_TRUE(db->Init(temp_dir.path()));
377 EXPECT_TRUE(db->Load(&load_entries));
378 // Convert the strings back to TestProto.
379 std::vector<TestProto> loaded_protos;
380 for (std::vector<std::string>::iterator it = load_entries.begin();
381 it != load_entries.end(); ++it) {
382 TestProto entry;
383 entry.ParseFromString(*it);
384 loaded_protos.push_back(entry);
386 ExpectEntryPointersEquals(model, loaded_protos);
389 TEST(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoad) {
390 TestLevelDBSaveAndLoad(false);
393 TEST(ProtoDatabaseImplLevelDBTest, TestDBCloseAndReopen) {
394 TestLevelDBSaveAndLoad(true);
397 } // namespace leveldb_proto