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 "chrome/browser/sync_file_system/drive_backend/leveldb_wrapper.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
14 #include "third_party/leveldatabase/src/include/leveldb/db.h"
15 #include "third_party/leveldatabase/src/include/leveldb/env.h"
17 namespace sync_file_system
{
18 namespace drive_backend
{
21 const std::string key
;
22 const std::string value
;
25 class LevelDBWrapperTest
: public testing::Test
{
27 ~LevelDBWrapperTest() override
{}
29 void SetUp() override
{
30 ASSERT_TRUE(database_dir_
.CreateUniqueTempDir());
31 in_memory_env_
.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
35 void TearDown() override
{
37 in_memory_env_
.reset();
40 void CreateDefaultDatabase() {
41 leveldb::DB
* db
= db_
->GetLevelDB();
43 // Expected contents are
44 // {"a": "1", "ab": "0", "bb": "3", "d": "4"}
45 const char* keys
[] = {"ab", "a", "d", "bb", "d"};
46 for (size_t i
= 0; i
< arraysize(keys
); ++i
) {
47 leveldb::Status status
=
48 db
->Put(leveldb::WriteOptions(), keys
[i
], base::Int64ToString(i
));
49 ASSERT_TRUE(status
.ok());
53 LevelDBWrapper
* GetDB() {
57 void CheckDBContents(const TestData expects
[], size_t size
) {
60 scoped_ptr
<LevelDBWrapper::Iterator
> itr
= db_
->NewIterator();
62 for (size_t i
= 0; i
< size
; ++i
) {
63 ASSERT_TRUE(itr
->Valid());
64 EXPECT_EQ(expects
[i
].key
, itr
->key().ToString());
65 EXPECT_EQ(expects
[i
].value
, itr
->value().ToString());
68 EXPECT_FALSE(itr
->Valid());
72 void InitializeLevelDB() {
73 leveldb::DB
* db
= nullptr;
74 leveldb::Options options
;
75 options
.create_if_missing
= true;
76 options
.max_open_files
= 0; // Use minimum.
77 options
.env
= in_memory_env_
.get();
78 leveldb::Status status
=
79 leveldb::DB::Open(options
, database_dir_
.path().AsUTF8Unsafe(), &db
);
80 ASSERT_TRUE(status
.ok());
82 db_
.reset(new LevelDBWrapper(make_scoped_ptr(db
)));
85 base::ScopedTempDir database_dir_
;
86 scoped_ptr
<leveldb::Env
> in_memory_env_
;
87 scoped_ptr
<LevelDBWrapper
> db_
;
90 TEST_F(LevelDBWrapperTest
, IteratorTest
) {
91 CreateDefaultDatabase();
92 scoped_ptr
<LevelDBWrapper::Iterator
> itr
= GetDB()->NewIterator();
95 EXPECT_TRUE(itr
->Valid());
96 EXPECT_EQ("a", itr
->key().ToString());
97 EXPECT_EQ("1", itr
->value().ToString());
100 EXPECT_TRUE(itr
->Valid());
101 EXPECT_EQ("ab", itr
->key().ToString());
102 EXPECT_EQ("0", itr
->value().ToString());
105 EXPECT_TRUE(itr
->Valid());
106 EXPECT_EQ("bb", itr
->key().ToString());
107 EXPECT_EQ("3", itr
->value().ToString());
110 EXPECT_TRUE(itr
->Valid());
111 EXPECT_EQ("d", itr
->key().ToString());
112 EXPECT_EQ("4", itr
->value().ToString());
115 EXPECT_FALSE(itr
->Valid());
118 EXPECT_TRUE(itr
->Valid());
119 EXPECT_EQ("a", itr
->key().ToString());
120 EXPECT_EQ("1", itr
->value().ToString());
123 EXPECT_TRUE(itr
->Valid());
124 EXPECT_EQ("ab", itr
->key().ToString());
125 EXPECT_EQ("0", itr
->value().ToString());
128 EXPECT_TRUE(itr
->Valid());
129 EXPECT_EQ("ab", itr
->key().ToString());
130 EXPECT_EQ("0", itr
->value().ToString());
132 EXPECT_EQ(0, GetDB()->num_puts());
133 EXPECT_EQ(1, GetDB()->num_deletes());
136 TEST_F(LevelDBWrapperTest
, Iterator2Test
) {
137 GetDB()->Put("a", "1");
138 GetDB()->Put("b", "2");
139 GetDB()->Put("c", "3");
140 // Keep pending transanctions on memory.
142 scoped_ptr
<LevelDBWrapper::Iterator
> itr
= GetDB()->NewIterator();
144 std::string prev_key
;
145 std::string prev_value
;
146 int loop_counter
= 0;
147 for (itr
->SeekToFirst(); itr
->Valid(); itr
->Next()) {
148 ASSERT_NE(prev_key
, itr
->key().ToString());
149 ASSERT_NE(prev_value
, itr
->value().ToString());
150 prev_key
= itr
->key().ToString();
151 prev_value
= itr
->value().ToString();
154 EXPECT_EQ(3, loop_counter
);
155 EXPECT_EQ("c", prev_key
);
156 EXPECT_EQ("3", prev_value
);
158 EXPECT_EQ(3, GetDB()->num_puts());
159 EXPECT_EQ(0, GetDB()->num_deletes());
162 TEST_F(LevelDBWrapperTest
, PutTest
) {
163 TestData merged_data
[] = {{"a", "1"}, {"aa", "new0"}, {"ab", "0"},
164 {"bb", "new2"}, {"c", "new1"}, {"d", "4"}};
165 TestData orig_data
[] = {{"a", "1"}, {"ab", "0"}, {"bb", "3"}, {"d", "4"}};
167 CreateDefaultDatabase();
169 // Add pending transactions.
170 GetDB()->Put("aa", "new0");
171 GetDB()->Put("c", "new1");
172 GetDB()->Put("bb", "new2"); // Overwrite an entry.
174 SCOPED_TRACE("PutTest_Pending");
175 CheckDBContents(merged_data
, arraysize(merged_data
));
177 EXPECT_EQ(3, GetDB()->num_puts());
178 // Remove all pending transactions.
180 EXPECT_EQ(0, GetDB()->num_puts());
182 SCOPED_TRACE("PutTest_Clear");
183 CheckDBContents(orig_data
, arraysize(orig_data
));
185 // Add pending transactions again, with commiting.
186 GetDB()->Put("aa", "new0");
187 GetDB()->Put("c", "new1");
188 GetDB()->Put("bb", "new2");
189 EXPECT_EQ(3, GetDB()->num_puts());
191 EXPECT_EQ(0, GetDB()->num_puts());
192 GetDB()->Clear(); // Clear just in case.
194 SCOPED_TRACE("PutTest_Commit");
195 CheckDBContents(merged_data
, arraysize(merged_data
));
198 TEST_F(LevelDBWrapperTest
, DeleteTest
) {
199 TestData merged_data
[] = {{"a", "1"}, {"aa", "new0"}, {"bb", "new2"},
201 TestData orig_data
[] = {{"a", "1"}, {"ab", "0"}, {"bb", "3"}, {"d", "4"}};
203 CreateDefaultDatabase();
205 // Add pending transactions.
206 GetDB()->Put("aa", "new0");
207 GetDB()->Put("c", "new1");
208 GetDB()->Put("bb", "new2"); // Overwrite an entry.
209 GetDB()->Delete("c"); // Remove a pending entry.
210 GetDB()->Delete("ab"); // Remove a committed entry.
212 EXPECT_EQ(3, GetDB()->num_puts());
213 EXPECT_EQ(2, GetDB()->num_deletes());
215 SCOPED_TRACE("DeleteTest_Pending");
216 CheckDBContents(merged_data
, arraysize(merged_data
));
218 // Remove all pending transactions.
221 SCOPED_TRACE("DeleteTest_Clear");
222 CheckDBContents(orig_data
, arraysize(orig_data
));
224 // Add pending transactions again, with commiting.
225 GetDB()->Put("aa", "new0");
226 GetDB()->Put("c", "new1");
227 GetDB()->Put("bb", "new2");
228 GetDB()->Delete("c");
229 GetDB()->Delete("ab");
233 EXPECT_EQ(0, GetDB()->num_puts());
234 EXPECT_EQ(0, GetDB()->num_deletes());
236 SCOPED_TRACE("DeleteTest_Commit");
237 CheckDBContents(merged_data
, arraysize(merged_data
));
240 } // namespace drive_backend
241 } // namespace sync_file_system