blob: 50f81677389dfd40f6e40b8b43ae0e5371d0666f [file] [log] [blame]
[email protected]2b894b82014-06-18 16:22:301// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]0664b5ab2013-09-23 04:14:452// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]2b894b82014-06-18 16:22:305#include "components/leveldb_proto/proto_database_impl.h"
[email protected]0664b5ab2013-09-23 04:14:456
avi26062922015-12-26 00:14:187#include <stddef.h>
dcheng84c358e2016-04-26 07:05:538
[email protected]0664b5ab2013-09-23 04:14:459#include <map>
dcheng84c358e2016-04-26 07:05:5310#include <memory>
dcheng51606352015-12-26 21:16:2311#include <utility>
[email protected]0664b5ab2013-09-23 04:14:4512
13#include "base/bind.h"
thestig819adcc82014-09-10 22:24:5314#include "base/files/file_util.h"
[email protected]0664b5ab2013-09-23 04:14:4515#include "base/files/scoped_temp_dir.h"
skyostilb0daa012015-06-02 19:03:4816#include "base/location.h"
dcheng84c358e2016-04-26 07:05:5317#include "base/memory/ptr_util.h"
[email protected]0664b5ab2013-09-23 04:14:4518#include "base/run_loop.h"
[email protected]e16968e2013-11-06 21:59:2519#include "base/threading/thread.h"
sside4aba362016-09-26 21:34:0020#include "base/trace_event/memory_dump_manager.h"
21#include "base/trace_event/process_memory_dump.h"
[email protected]2b894b82014-06-18 16:22:3022#include "components/leveldb_proto/leveldb_database.h"
23#include "components/leveldb_proto/testing/proto/test.pb.h"
[email protected]0664b5ab2013-09-23 04:14:4524#include "testing/gmock/include/gmock/gmock.h"
25#include "testing/gtest/include/gtest/gtest.h"
cjhopman1aad1742014-11-20 00:30:0626#include "third_party/leveldatabase/src/include/leveldb/options.h"
[email protected]0664b5ab2013-09-23 04:14:4527
28using base::MessageLoop;
29using base::ScopedTempDir;
30using testing::Invoke;
31using testing::Return;
tschumann108e9c22016-10-04 13:34:5732using testing::UnorderedElementsAre;
[email protected]0664b5ab2013-09-23 04:14:4533using testing::_;
34
[email protected]2b894b82014-06-18 16:22:3035namespace leveldb_proto {
[email protected]0664b5ab2013-09-23 04:14:4536
37namespace {
38
[email protected]2b894b82014-06-18 16:22:3039typedef std::map<std::string, TestProto> EntryMap;
[email protected]0664b5ab2013-09-23 04:14:4540
cmumford51878062015-10-13 17:02:0841const char kTestLevelDBClientName[] = "Test";
42
[email protected]2b894b82014-06-18 16:22:3043class MockDB : public LevelDB {
[email protected]0664b5ab2013-09-23 04:14:4544 public:
treibd0124d402016-11-24 21:54:3545 MOCK_METHOD1(Init, bool(const leveldb_proto::Options& options));
[email protected]2b894b82014-06-18 16:22:3046 MOCK_METHOD2(Save, bool(const KeyValueVector&, const KeyVector&));
47 MOCK_METHOD1(Load, bool(std::vector<std::string>*));
treib4fe73e32016-06-16 15:36:1548 MOCK_METHOD3(Get, bool(const std::string&, bool*, std::string*));
[email protected]0664b5ab2013-09-23 04:14:4549
treib4fe73e32016-06-16 15:36:1550 MockDB() : LevelDB(kTestLevelDBClientName) {}
[email protected]0664b5ab2013-09-23 04:14:4551};
52
53class MockDatabaseCaller {
54 public:
55 MOCK_METHOD1(InitCallback, void(bool));
jianli6dc78d42016-01-20 23:30:4956 MOCK_METHOD1(DestroyCallback, void(bool));
[email protected]0664b5ab2013-09-23 04:14:4557 MOCK_METHOD1(SaveCallback, void(bool));
dcheng84c358e2016-04-26 07:05:5358 void LoadCallback(bool success,
59 std::unique_ptr<std::vector<TestProto>> entries) {
[email protected]0664b5ab2013-09-23 04:14:4560 LoadCallback1(success, entries.get());
61 }
[email protected]2b894b82014-06-18 16:22:3062 MOCK_METHOD2(LoadCallback1, void(bool, std::vector<TestProto>*));
treib4fe73e32016-06-16 15:36:1563 void GetCallback(bool success, std::unique_ptr<TestProto> entry) {
64 GetCallback1(success, entry.get());
65 }
66 MOCK_METHOD2(GetCallback1, void(bool, TestProto*));
[email protected]0664b5ab2013-09-23 04:14:4567};
68
69} // namespace
70
treibd0124d402016-11-24 21:54:3571bool operator==(const Options& lhs, const Options& rhs) {
72 return lhs.database_dir == rhs.database_dir &&
73 lhs.write_buffer_size == rhs.write_buffer_size;
74}
75
[email protected]0664b5ab2013-09-23 04:14:4576EntryMap GetSmallModel() {
77 EntryMap model;
78
[email protected]2b894b82014-06-18 16:22:3079 model["0"].set_id("0");
80 model["0"].set_data("http://foo.com/1");
[email protected]0664b5ab2013-09-23 04:14:4581
[email protected]2b894b82014-06-18 16:22:3082 model["1"].set_id("1");
83 model["1"].set_data("http://bar.com/all");
[email protected]0664b5ab2013-09-23 04:14:4584
[email protected]2b894b82014-06-18 16:22:3085 model["2"].set_id("2");
86 model["2"].set_data("http://baz.com/1");
[email protected]0664b5ab2013-09-23 04:14:4587
88 return model;
89}
90
[email protected]2b894b82014-06-18 16:22:3091void ExpectEntryPointersEquals(EntryMap expected,
92 const std::vector<TestProto>& actual) {
[email protected]0664b5ab2013-09-23 04:14:4593 EXPECT_EQ(expected.size(), actual.size());
94 for (size_t i = 0; i < actual.size(); i++) {
[email protected]2b894b82014-06-18 16:22:3095 EntryMap::iterator expected_it = expected.find(actual[i].id());
[email protected]0664b5ab2013-09-23 04:14:4596 EXPECT_TRUE(expected_it != expected.end());
97 std::string serialized_expected = expected_it->second.SerializeAsString();
98 std::string serialized_actual = actual[i].SerializeAsString();
99 EXPECT_EQ(serialized_expected, serialized_actual);
100 expected.erase(expected_it);
101 }
102}
103
[email protected]2b894b82014-06-18 16:22:30104class ProtoDatabaseImplTest : public testing::Test {
[email protected]0664b5ab2013-09-23 04:14:45105 public:
dcheng30a1b1542014-10-29 21:27:50106 void SetUp() override {
[email protected]0664b5ab2013-09-23 04:14:45107 main_loop_.reset(new MessageLoop());
skyostilb0daa012015-06-02 19:03:48108 db_.reset(new ProtoDatabaseImpl<TestProto>(main_loop_->task_runner()));
[email protected]0664b5ab2013-09-23 04:14:45109 }
110
dcheng30a1b1542014-10-29 21:27:50111 void TearDown() override {
[email protected]e16968e2013-11-06 21:59:25112 db_.reset();
113 base::RunLoop().RunUntilIdle();
114 main_loop_.reset();
[email protected]0664b5ab2013-09-23 04:14:45115 }
116
dcheng84c358e2016-04-26 07:05:53117 std::unique_ptr<ProtoDatabaseImpl<TestProto>> db_;
118 std::unique_ptr<MessageLoop> main_loop_;
[email protected]0664b5ab2013-09-23 04:14:45119};
120
[email protected]2b894b82014-06-18 16:22:30121// Test that ProtoDatabaseImpl calls Init on the underlying database and that
[email protected]0664b5ab2013-09-23 04:14:45122// the caller's InitCallback is called with the correct value.
[email protected]2b894b82014-06-18 16:22:30123TEST_F(ProtoDatabaseImplTest, TestDBInitSuccess) {
[email protected]0664b5ab2013-09-23 04:14:45124 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
125
126 MockDB* mock_db = new MockDB();
treibd0124d402016-11-24 21:54:35127 EXPECT_CALL(*mock_db, Init(Options(path))).WillOnce(Return(true));
[email protected]0664b5ab2013-09-23 04:14:45128
129 MockDatabaseCaller caller;
130 EXPECT_CALL(caller, InitCallback(true));
131
132 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53133 base::WrapUnique(mock_db), path,
[email protected]0664b5ab2013-09-23 04:14:45134 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
135
136 base::RunLoop().RunUntilIdle();
137}
138
[email protected]2b894b82014-06-18 16:22:30139TEST_F(ProtoDatabaseImplTest, TestDBInitFailure) {
[email protected]0664b5ab2013-09-23 04:14:45140 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
141
142 MockDB* mock_db = new MockDB();
treibd0124d402016-11-24 21:54:35143 EXPECT_CALL(*mock_db, Init(Options(path))).WillOnce(Return(false));
[email protected]0664b5ab2013-09-23 04:14:45144
145 MockDatabaseCaller caller;
146 EXPECT_CALL(caller, InitCallback(false));
147
148 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53149 base::WrapUnique(mock_db), path,
[email protected]0664b5ab2013-09-23 04:14:45150 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
151
152 base::RunLoop().RunUntilIdle();
153}
154
155ACTION_P(AppendLoadEntries, model) {
[email protected]2b894b82014-06-18 16:22:30156 std::vector<std::string>* output = arg0;
peter7cdc93c2015-07-30 14:03:14157 for (const auto& pair : model)
158 output->push_back(pair.second.SerializeAsString());
159
[email protected]0664b5ab2013-09-23 04:14:45160 return true;
161}
162
163ACTION_P(VerifyLoadEntries, expected) {
[email protected]2b894b82014-06-18 16:22:30164 std::vector<TestProto>* actual = arg1;
[email protected]0664b5ab2013-09-23 04:14:45165 ExpectEntryPointersEquals(expected, *actual);
166}
167
[email protected]2b894b82014-06-18 16:22:30168// Test that ProtoDatabaseImpl calls Load on the underlying database and that
[email protected]0664b5ab2013-09-23 04:14:45169// the caller's LoadCallback is called with the correct success value. Also
170// confirms that on success, the expected entries are passed to the caller's
171// LoadCallback.
[email protected]2b894b82014-06-18 16:22:30172TEST_F(ProtoDatabaseImplTest, TestDBLoadSuccess) {
[email protected]0664b5ab2013-09-23 04:14:45173 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
174
175 MockDB* mock_db = new MockDB();
176 MockDatabaseCaller caller;
177 EntryMap model = GetSmallModel();
178
179 EXPECT_CALL(*mock_db, Init(_));
180 EXPECT_CALL(caller, InitCallback(_));
181 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53182 base::WrapUnique(mock_db), path,
[email protected]0664b5ab2013-09-23 04:14:45183 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
184
185 EXPECT_CALL(*mock_db, Load(_)).WillOnce(AppendLoadEntries(model));
186 EXPECT_CALL(caller, LoadCallback1(true, _))
187 .WillOnce(VerifyLoadEntries(testing::ByRef(model)));
188 db_->LoadEntries(
189 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller)));
190
191 base::RunLoop().RunUntilIdle();
192}
193
[email protected]2b894b82014-06-18 16:22:30194TEST_F(ProtoDatabaseImplTest, TestDBLoadFailure) {
[email protected]0664b5ab2013-09-23 04:14:45195 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
196
197 MockDB* mock_db = new MockDB();
198 MockDatabaseCaller caller;
199
200 EXPECT_CALL(*mock_db, Init(_));
201 EXPECT_CALL(caller, InitCallback(_));
202 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53203 base::WrapUnique(mock_db), path,
[email protected]0664b5ab2013-09-23 04:14:45204 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
205
206 EXPECT_CALL(*mock_db, Load(_)).WillOnce(Return(false));
207 EXPECT_CALL(caller, LoadCallback1(false, _));
208 db_->LoadEntries(
209 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller)));
210
211 base::RunLoop().RunUntilIdle();
212}
213
treib4fe73e32016-06-16 15:36:15214ACTION_P(SetGetEntry, model) {
215 const std::string& key = arg0;
216 bool* found = arg1;
217 std::string* output = arg2;
218 auto it = model.find(key);
219 if (it == model.end()) {
220 *found = false;
221 } else {
222 *found = true;
223 *output = it->second.SerializeAsString();
224 }
225 return true;
226}
227
228ACTION_P(VerifyGetEntry, expected) {
229 TestProto* actual = arg1;
230 EXPECT_EQ(expected.SerializeAsString(), actual->SerializeAsString());
231}
232
233TEST_F(ProtoDatabaseImplTest, TestDBGetSuccess) {
234 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
235
236 MockDB* mock_db = new MockDB();
237 MockDatabaseCaller caller;
238 EntryMap model = GetSmallModel();
239
240 EXPECT_CALL(*mock_db, Init(_));
241 EXPECT_CALL(caller, InitCallback(_));
242 db_->InitWithDatabase(
243 base::WrapUnique(mock_db), path,
244 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
245
246 std::string key("1");
247 ASSERT_TRUE(model.count(key));
248 EXPECT_CALL(*mock_db, Get(key, _, _)).WillOnce(SetGetEntry(model));
249 EXPECT_CALL(caller, GetCallback1(true, _))
250 .WillOnce(VerifyGetEntry(model[key]));
251 db_->GetEntry(key, base::Bind(&MockDatabaseCaller::GetCallback,
252 base::Unretained(&caller)));
253
254 base::RunLoop().RunUntilIdle();
255}
256
tschumann108e9c22016-10-04 13:34:57257TEST(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoadKeys) {
258 base::MessageLoop main_loop;
259
260 ScopedTempDir temp_dir;
261 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
262 base::Thread db_thread("dbthread");
263 ASSERT_TRUE(db_thread.Start());
264 std::unique_ptr<ProtoDatabaseImpl<TestProto>> db(
265 new ProtoDatabaseImpl<TestProto>(db_thread.task_runner()));
266
267 auto expect_init_success =
268 base::Bind([](bool success) { EXPECT_TRUE(success); });
269 db->Init(kTestLevelDBClientName, temp_dir.GetPath(), expect_init_success);
270
271 base::RunLoop run_update_entries;
272 auto expect_update_success = base::Bind(
273 [](base::Closure signal, bool success) {
274 EXPECT_TRUE(success);
275 signal.Run();
276 },
277 run_update_entries.QuitClosure());
278 TestProto test_proto;
279 test_proto.set_data("some data");
280 ProtoDatabase<TestProto>::KeyEntryVector data_set(
281 {{"0", test_proto}, {"1", test_proto}, {"2", test_proto}});
282 db->UpdateEntries(
283 base::MakeUnique<ProtoDatabase<TestProto>::KeyEntryVector>(data_set),
284 base::MakeUnique<std::vector<std::string>>(), expect_update_success);
285 run_update_entries.Run();
286
287 base::RunLoop run_load_keys;
288 auto verify_loaded_keys = base::Bind(
289 [](base::Closure signal, bool success,
290 std::unique_ptr<std::vector<std::string>> keys) {
291 EXPECT_TRUE(success);
292 EXPECT_THAT(*keys, UnorderedElementsAre("0", "1", "2"));
293 signal.Run();
294 },
295 run_load_keys.QuitClosure());
296 db->LoadKeys(verify_loaded_keys);
297 run_load_keys.Run();
298
299 // Shutdown database.
300 db.reset();
301 base::RunLoop run_destruction;
302 db_thread.task_runner()->PostTaskAndReply(
303 FROM_HERE, base::Bind(base::DoNothing), run_destruction.QuitClosure());
304 run_destruction.Run();
305}
306
treib4fe73e32016-06-16 15:36:15307TEST_F(ProtoDatabaseImplTest, TestDBGetNotFound) {
308 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
309
310 MockDB* mock_db = new MockDB();
311 MockDatabaseCaller caller;
312 EntryMap model = GetSmallModel();
313
314 EXPECT_CALL(*mock_db, Init(_));
315 EXPECT_CALL(caller, InitCallback(_));
316 db_->InitWithDatabase(
317 base::WrapUnique(mock_db), path,
318 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
319
320 std::string key("does_not_exist");
321 ASSERT_FALSE(model.count(key));
322 EXPECT_CALL(*mock_db, Get(key, _, _)).WillOnce(SetGetEntry(model));
323 EXPECT_CALL(caller, GetCallback1(true, nullptr));
324 db_->GetEntry(key, base::Bind(&MockDatabaseCaller::GetCallback,
325 base::Unretained(&caller)));
326
327 base::RunLoop().RunUntilIdle();
328}
329
330TEST_F(ProtoDatabaseImplTest, TestDBGetFailure) {
331 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
332
333 MockDB* mock_db = new MockDB();
334 MockDatabaseCaller caller;
335 EntryMap model = GetSmallModel();
336
337 EXPECT_CALL(*mock_db, Init(_));
338 EXPECT_CALL(caller, InitCallback(_));
339 db_->InitWithDatabase(
340 base::WrapUnique(mock_db), path,
341 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
342
343 std::string key("does_not_exist");
344 ASSERT_FALSE(model.count(key));
345 EXPECT_CALL(*mock_db, Get(key, _, _)).WillOnce(Return(false));
346 EXPECT_CALL(caller, GetCallback1(false, nullptr));
347 db_->GetEntry(key, base::Bind(&MockDatabaseCaller::GetCallback,
348 base::Unretained(&caller)));
349
350 base::RunLoop().RunUntilIdle();
351}
352
[email protected]4b79f61e2013-12-04 05:43:08353ACTION_P(VerifyUpdateEntries, expected) {
[email protected]2b894b82014-06-18 16:22:30354 const KeyValueVector actual = arg0;
355 // Create a vector of TestProto from |actual| to reuse the comparison
356 // function.
357 std::vector<TestProto> extracted_entries;
peter7cdc93c2015-07-30 14:03:14358 for (const auto& pair : actual) {
[email protected]2b894b82014-06-18 16:22:30359 TestProto entry;
peter7cdc93c2015-07-30 14:03:14360 if (!entry.ParseFromString(pair.second)) {
361 ADD_FAILURE() << "Unable to deserialize the protobuf";
362 return false;
363 }
364
[email protected]2b894b82014-06-18 16:22:30365 extracted_entries.push_back(entry);
366 }
peter7cdc93c2015-07-30 14:03:14367
[email protected]2b894b82014-06-18 16:22:30368 ExpectEntryPointersEquals(expected, extracted_entries);
[email protected]0664b5ab2013-09-23 04:14:45369 return true;
370}
371
[email protected]2b894b82014-06-18 16:22:30372// Test that ProtoDatabaseImpl calls Save on the underlying database with the
[email protected]0664b5ab2013-09-23 04:14:45373// correct entries to save and that the caller's SaveCallback is called with the
374// correct success value.
[email protected]2b894b82014-06-18 16:22:30375TEST_F(ProtoDatabaseImplTest, TestDBSaveSuccess) {
[email protected]0664b5ab2013-09-23 04:14:45376 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
377
378 MockDB* mock_db = new MockDB();
379 MockDatabaseCaller caller;
380 EntryMap model = GetSmallModel();
381
382 EXPECT_CALL(*mock_db, Init(_));
383 EXPECT_CALL(caller, InitCallback(_));
384 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53385 base::WrapUnique(mock_db), path,
[email protected]0664b5ab2013-09-23 04:14:45386 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
387
dcheng84c358e2016-04-26 07:05:53388 std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
[email protected]2b894b82014-06-18 16:22:30389 new ProtoDatabase<TestProto>::KeyEntryVector());
peter7cdc93c2015-07-30 14:03:14390 for (const auto& pair : model)
391 entries->push_back(std::make_pair(pair.second.id(), pair.second));
392
dcheng84c358e2016-04-26 07:05:53393 std::unique_ptr<KeyVector> keys_to_remove(new KeyVector());
[email protected]0664b5ab2013-09-23 04:14:45394
[email protected]4b79f61e2013-12-04 05:43:08395 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(VerifyUpdateEntries(model));
[email protected]0664b5ab2013-09-23 04:14:45396 EXPECT_CALL(caller, SaveCallback(true));
[email protected]4b79f61e2013-12-04 05:43:08397 db_->UpdateEntries(
dcheng51606352015-12-26 21:16:23398 std::move(entries), std::move(keys_to_remove),
[email protected]0664b5ab2013-09-23 04:14:45399 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
400
401 base::RunLoop().RunUntilIdle();
402}
403
[email protected]2b894b82014-06-18 16:22:30404TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) {
[email protected]0664b5ab2013-09-23 04:14:45405 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
406
407 MockDB* mock_db = new MockDB();
408 MockDatabaseCaller caller;
dcheng84c358e2016-04-26 07:05:53409 std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
[email protected]2b894b82014-06-18 16:22:30410 new ProtoDatabase<TestProto>::KeyEntryVector());
dcheng84c358e2016-04-26 07:05:53411 std::unique_ptr<KeyVector> keys_to_remove(new KeyVector());
[email protected]0664b5ab2013-09-23 04:14:45412
413 EXPECT_CALL(*mock_db, Init(_));
414 EXPECT_CALL(caller, InitCallback(_));
415 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53416 base::WrapUnique(mock_db), path,
[email protected]0664b5ab2013-09-23 04:14:45417 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
418
[email protected]4b79f61e2013-12-04 05:43:08419 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false));
[email protected]0664b5ab2013-09-23 04:14:45420 EXPECT_CALL(caller, SaveCallback(false));
[email protected]4b79f61e2013-12-04 05:43:08421 db_->UpdateEntries(
dcheng51606352015-12-26 21:16:23422 std::move(entries), std::move(keys_to_remove),
[email protected]0664b5ab2013-09-23 04:14:45423 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
424
425 base::RunLoop().RunUntilIdle();
426}
427
[email protected]2b894b82014-06-18 16:22:30428// Test that ProtoDatabaseImpl calls Save on the underlying database with the
[email protected]4b79f61e2013-12-04 05:43:08429// correct entries to delete and that the caller's SaveCallback is called with
430// the correct success value.
[email protected]2b894b82014-06-18 16:22:30431TEST_F(ProtoDatabaseImplTest, TestDBRemoveSuccess) {
[email protected]4b79f61e2013-12-04 05:43:08432 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
433
434 MockDB* mock_db = new MockDB();
435 MockDatabaseCaller caller;
436 EntryMap model = GetSmallModel();
437
438 EXPECT_CALL(*mock_db, Init(_));
439 EXPECT_CALL(caller, InitCallback(_));
440 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53441 base::WrapUnique(mock_db), path,
[email protected]4b79f61e2013-12-04 05:43:08442 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
443
dcheng84c358e2016-04-26 07:05:53444 std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
[email protected]2b894b82014-06-18 16:22:30445 new ProtoDatabase<TestProto>::KeyEntryVector());
dcheng84c358e2016-04-26 07:05:53446 std::unique_ptr<KeyVector> keys_to_remove(new KeyVector());
peter7cdc93c2015-07-30 14:03:14447 for (const auto& pair : model)
448 keys_to_remove->push_back(pair.second.id());
[email protected]4b79f61e2013-12-04 05:43:08449
[email protected]2b894b82014-06-18 16:22:30450 KeyVector keys_copy(*keys_to_remove.get());
451 EXPECT_CALL(*mock_db, Save(_, keys_copy)).WillOnce(Return(true));
[email protected]4b79f61e2013-12-04 05:43:08452 EXPECT_CALL(caller, SaveCallback(true));
453 db_->UpdateEntries(
dcheng51606352015-12-26 21:16:23454 std::move(entries), std::move(keys_to_remove),
[email protected]4b79f61e2013-12-04 05:43:08455 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
456
457 base::RunLoop().RunUntilIdle();
458}
459
[email protected]2b894b82014-06-18 16:22:30460TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) {
[email protected]4b79f61e2013-12-04 05:43:08461 base::FilePath path(FILE_PATH_LITERAL("/fake/path"));
462
463 MockDB* mock_db = new MockDB();
464 MockDatabaseCaller caller;
dcheng84c358e2016-04-26 07:05:53465 std::unique_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries(
[email protected]2b894b82014-06-18 16:22:30466 new ProtoDatabase<TestProto>::KeyEntryVector());
dcheng84c358e2016-04-26 07:05:53467 std::unique_ptr<KeyVector> keys_to_remove(new KeyVector());
[email protected]4b79f61e2013-12-04 05:43:08468
469 EXPECT_CALL(*mock_db, Init(_));
470 EXPECT_CALL(caller, InitCallback(_));
471 db_->InitWithDatabase(
dcheng84c358e2016-04-26 07:05:53472 base::WrapUnique(mock_db), path,
[email protected]4b79f61e2013-12-04 05:43:08473 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
474
475 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false));
476 EXPECT_CALL(caller, SaveCallback(false));
477 db_->UpdateEntries(
dcheng51606352015-12-26 21:16:23478 std::move(entries), std::move(keys_to_remove),
[email protected]4b79f61e2013-12-04 05:43:08479 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller)));
480
481 base::RunLoop().RunUntilIdle();
482}
483
[email protected]e16968e2013-11-06 21:59:25484// This tests that normal usage of the real database does not cause any
485// threading violations.
[email protected]2b894b82014-06-18 16:22:30486TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) {
[email protected]e16968e2013-11-06 21:59:25487 base::MessageLoop main_loop;
488
489 ScopedTempDir temp_dir;
490 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
491
492 base::Thread db_thread("dbthread");
493 ASSERT_TRUE(db_thread.Start());
494
dcheng84c358e2016-04-26 07:05:53495 std::unique_ptr<ProtoDatabaseImpl<TestProto>> db(
skyostilb0daa012015-06-02 19:03:48496 new ProtoDatabaseImpl<TestProto>(db_thread.task_runner()));
[email protected]e16968e2013-11-06 21:59:25497
498 MockDatabaseCaller caller;
499 EXPECT_CALL(caller, InitCallback(_));
cmumford51878062015-10-13 17:02:08500 db->Init(
vabr0c237ae2016-09-14 09:24:28501 kTestLevelDBClientName, temp_dir.GetPath(),
cmumford51878062015-10-13 17:02:08502 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
[email protected]e16968e2013-11-06 21:59:25503
504 db.reset();
505
506 base::RunLoop run_loop;
skyostilb0daa012015-06-02 19:03:48507 db_thread.task_runner()->PostTaskAndReply(
[email protected]e16968e2013-11-06 21:59:25508 FROM_HERE, base::Bind(base::DoNothing), run_loop.QuitClosure());
509 run_loop.Run();
510}
511
jianli6dc78d42016-01-20 23:30:49512// This tests that normal usage of the real database does not cause any
513// threading violations.
514TEST(ProtoDatabaseImplThreadingTest, TestDBDestroy) {
515 base::MessageLoop main_loop;
516
517 ScopedTempDir temp_dir;
518 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
519
520 base::Thread db_thread("dbthread");
521 ASSERT_TRUE(db_thread.Start());
522
dcheng84c358e2016-04-26 07:05:53523 std::unique_ptr<ProtoDatabaseImpl<TestProto>> db(
jianli6dc78d42016-01-20 23:30:49524 new ProtoDatabaseImpl<TestProto>(db_thread.task_runner()));
525
526 MockDatabaseCaller caller;
527 EXPECT_CALL(caller, InitCallback(_));
528 db->Init(
vabr0c237ae2016-09-14 09:24:28529 kTestLevelDBClientName, temp_dir.GetPath(),
jianli6dc78d42016-01-20 23:30:49530 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller)));
531
532 EXPECT_CALL(caller, DestroyCallback(_));
533 db->Destroy(base::Bind(&MockDatabaseCaller::DestroyCallback,
534 base::Unretained(&caller)));
535
536 db.reset();
537
538 base::RunLoop run_loop;
539 db_thread.task_runner()->PostTaskAndReply(
540 FROM_HERE, base::Bind(base::DoNothing), run_loop.QuitClosure());
541 run_loop.Run();
542}
543
[email protected]0664b5ab2013-09-23 04:14:45544// Test that the LevelDB properly saves entries and that load returns the saved
545// entries. If |close_after_save| is true, the database will be closed after
546// saving and then re-opened to ensure that the data is properly persisted.
547void TestLevelDBSaveAndLoad(bool close_after_save) {
sside4aba362016-09-26 21:34:00548 base::MessageLoop main_loop;
549
[email protected]0664b5ab2013-09-23 04:14:45550 ScopedTempDir temp_dir;
551 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
552
553 EntryMap model = GetSmallModel();
[email protected]2b894b82014-06-18 16:22:30554
555 KeyValueVector save_entries;
556 std::vector<std::string> load_entries;
557 KeyVector remove_keys;
[email protected]0664b5ab2013-09-23 04:14:45558
peter7cdc93c2015-07-30 14:03:14559 for (const auto& pair : model) {
[email protected]2b894b82014-06-18 16:22:30560 save_entries.push_back(
peter7cdc93c2015-07-30 14:03:14561 std::make_pair(pair.second.id(), pair.second.SerializeAsString()));
[email protected]0664b5ab2013-09-23 04:14:45562 }
563
dcheng84c358e2016-04-26 07:05:53564 std::unique_ptr<LevelDB> db(new LevelDB(kTestLevelDBClientName));
vabr0c237ae2016-09-14 09:24:28565 EXPECT_TRUE(db->Init(temp_dir.GetPath()));
[email protected]2b894b82014-06-18 16:22:30566 EXPECT_TRUE(db->Save(save_entries, remove_keys));
[email protected]0664b5ab2013-09-23 04:14:45567
568 if (close_after_save) {
cmumford51878062015-10-13 17:02:08569 db.reset(new LevelDB(kTestLevelDBClientName));
vabr0c237ae2016-09-14 09:24:28570 EXPECT_TRUE(db->Init(temp_dir.GetPath()));
[email protected]0664b5ab2013-09-23 04:14:45571 }
572
573 EXPECT_TRUE(db->Load(&load_entries));
peter7cdc93c2015-07-30 14:03:14574
[email protected]2b894b82014-06-18 16:22:30575 // Convert the strings back to TestProto.
576 std::vector<TestProto> loaded_protos;
peter7cdc93c2015-07-30 14:03:14577 for (const auto& serialized_entry : load_entries) {
[email protected]2b894b82014-06-18 16:22:30578 TestProto entry;
peter7cdc93c2015-07-30 14:03:14579 ASSERT_TRUE(entry.ParseFromString(serialized_entry));
[email protected]2b894b82014-06-18 16:22:30580 loaded_protos.push_back(entry);
581 }
peter7cdc93c2015-07-30 14:03:14582
[email protected]2b894b82014-06-18 16:22:30583 ExpectEntryPointersEquals(model, loaded_protos);
[email protected]0664b5ab2013-09-23 04:14:45584}
585
[email protected]2b894b82014-06-18 16:22:30586TEST(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoad) {
[email protected]0664b5ab2013-09-23 04:14:45587 TestLevelDBSaveAndLoad(false);
588}
589
[email protected]2b894b82014-06-18 16:22:30590TEST(ProtoDatabaseImplLevelDBTest, TestDBCloseAndReopen) {
[email protected]0664b5ab2013-09-23 04:14:45591 TestLevelDBSaveAndLoad(true);
592}
593
cjhopman1aad1742014-11-20 00:30:06594TEST(ProtoDatabaseImplLevelDBTest, TestDBInitFail) {
595 ScopedTempDir temp_dir;
596 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
597
598 leveldb::Options options;
599 options.create_if_missing = false;
dcheng84c358e2016-04-26 07:05:53600 std::unique_ptr<LevelDB> db(new LevelDB(kTestLevelDBClientName));
cjhopman1aad1742014-11-20 00:30:06601
602 KeyValueVector save_entries;
603 std::vector<std::string> load_entries;
604 KeyVector remove_keys;
605
vabr0c237ae2016-09-14 09:24:28606 EXPECT_FALSE(db->InitWithOptions(temp_dir.GetPath(), options));
cjhopman1aad1742014-11-20 00:30:06607 EXPECT_FALSE(db->Load(&load_entries));
608 EXPECT_FALSE(db->Save(save_entries, remove_keys));
609}
610
peter36177072015-07-23 14:36:09611TEST(ProtoDatabaseImplLevelDBTest, TestMemoryDatabase) {
sside4aba362016-09-26 21:34:00612 base::MessageLoop main_loop;
613
dcheng84c358e2016-04-26 07:05:53614 std::unique_ptr<LevelDB> db(new LevelDB(kTestLevelDBClientName));
peter36177072015-07-23 14:36:09615
616 std::vector<std::string> load_entries;
617
618 ASSERT_TRUE(db->Init(base::FilePath()));
619
620 ASSERT_TRUE(db->Load(&load_entries));
621 EXPECT_EQ(0u, load_entries.size());
622
623 KeyValueVector save_entries(1, std::make_pair("foo", "bar"));
624 KeyVector remove_keys;
625
626 ASSERT_TRUE(db->Save(save_entries, remove_keys));
627
628 std::vector<std::string> second_load_entries;
629
630 ASSERT_TRUE(db->Load(&second_load_entries));
631 EXPECT_EQ(1u, second_load_entries.size());
632}
633
sside4aba362016-09-26 21:34:00634TEST(ProtoDatabaseImplLevelDBTest, TestOnMemoryDumpEmitsData) {
635 base::MessageLoop main_loop;
636 std::unique_ptr<LevelDB> db(new LevelDB(kTestLevelDBClientName));
637 std::vector<std::string> load_entries;
638 ASSERT_TRUE(db->Init(base::FilePath()));
639 KeyValueVector save_entries(1, std::make_pair("foo", "bar"));
640 KeyVector remove_keys;
641 ASSERT_TRUE(db->Save(save_entries, remove_keys));
642
643 base::trace_event::MemoryDumpArgs dump_args = {
644 base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
645 std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump(
646 new base::trace_event::ProcessMemoryDump(nullptr, dump_args));
647 db->OnMemoryDump(dump_args, process_memory_dump.get());
648
649 const auto& allocator_dumps = process_memory_dump->allocator_dumps();
650 const char* system_allocator_pool_name =
651 base::trace_event::MemoryDumpManager::GetInstance()
652 ->system_allocator_pool_name();
653 size_t expected_dump_count = system_allocator_pool_name ? 2 : 1;
654 EXPECT_EQ(expected_dump_count, allocator_dumps.size());
655 for (const auto& dump : allocator_dumps) {
656 ASSERT_TRUE(dump.first.find("leveldb/leveldb_proto/") == 0 ||
657 dump.first.find(system_allocator_pool_name) == 0);
658 }
659}
660
[email protected]2b894b82014-06-18 16:22:30661} // namespace leveldb_proto