1 // Copyright (c) 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.
4
5 #include <algorithm>
6 #include <cstring>
7 #include <string>
8
9 #include "base/files/file.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_piece.h"
14 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
15 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
16 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
17 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/leveldatabase/env_chromium.h"
20 #include "third_party/leveldatabase/env_idb.h"
21
22 namespace content {
23
24 namespace {
25
26 class SimpleComparator : public LevelDBComparator {
27 public:
Compare(const base::StringPiece & a,const base::StringPiece & b) const28 virtual int Compare(const base::StringPiece& a,
29 const base::StringPiece& b) const OVERRIDE {
30 size_t len = std::min(a.size(), b.size());
31 return memcmp(a.begin(), b.begin(), len);
32 }
Name() const33 virtual const char* Name() const OVERRIDE { return "temp_comparator"; }
34 };
35
36 } // namespace
37
TEST(LevelDBDatabaseTest,CorruptionTest)38 TEST(LevelDBDatabaseTest, CorruptionTest) {
39 base::ScopedTempDir temp_directory;
40 ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
41
42 const std::string key("key");
43 const std::string value("value");
44 std::string put_value;
45 std::string got_value;
46 SimpleComparator comparator;
47
48 scoped_ptr<LevelDBDatabase> leveldb;
49 LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
50 EXPECT_TRUE(leveldb);
51 put_value = value;
52 leveldb::Status status = leveldb->Put(key, &put_value);
53 EXPECT_TRUE(status.ok());
54 leveldb.Pass();
55 EXPECT_FALSE(leveldb);
56
57 LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
58 EXPECT_TRUE(leveldb);
59 bool found = false;
60 status = leveldb->Get(key, &got_value, &found);
61 EXPECT_TRUE(status.ok());
62 EXPECT_TRUE(found);
63 EXPECT_EQ(value, got_value);
64 leveldb.Pass();
65 EXPECT_FALSE(leveldb);
66
67 base::FilePath file_path = temp_directory.path().AppendASCII("CURRENT");
68 base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_WRITE);
69 file.SetLength(0);
70 file.Close();
71
72 status = LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
73 EXPECT_FALSE(leveldb);
74 EXPECT_FALSE(status.ok());
75
76 status = LevelDBDatabase::Destroy(temp_directory.path());
77 EXPECT_TRUE(status.ok());
78
79 status = LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
80 EXPECT_TRUE(status.ok());
81 EXPECT_TRUE(leveldb);
82 status = leveldb->Get(key, &got_value, &found);
83 EXPECT_TRUE(status.ok());
84 EXPECT_FALSE(found);
85 }
86
TEST(LevelDBDatabaseTest,Transaction)87 TEST(LevelDBDatabaseTest, Transaction) {
88 base::ScopedTempDir temp_directory;
89 ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
90
91 const std::string key("key");
92 std::string got_value;
93 std::string put_value;
94 SimpleComparator comparator;
95
96 scoped_ptr<LevelDBDatabase> leveldb;
97 LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
98 EXPECT_TRUE(leveldb);
99
100 const std::string old_value("value");
101 put_value = old_value;
102 leveldb::Status status = leveldb->Put(key, &put_value);
103 EXPECT_TRUE(status.ok());
104
105 scoped_refptr<LevelDBTransaction> transaction =
106 new LevelDBTransaction(leveldb.get());
107
108 const std::string new_value("new value");
109 put_value = new_value;
110 status = leveldb->Put(key, &put_value);
111 EXPECT_TRUE(status.ok());
112
113 bool found = false;
114 status = transaction->Get(key, &got_value, &found);
115 EXPECT_TRUE(status.ok());
116 EXPECT_TRUE(found);
117 EXPECT_EQ(comparator.Compare(got_value, old_value), 0);
118
119 found = false;
120 status = leveldb->Get(key, &got_value, &found);
121 EXPECT_TRUE(status.ok());
122 EXPECT_TRUE(found);
123 EXPECT_EQ(comparator.Compare(got_value, new_value), 0);
124
125 const std::string added_key("added key");
126 const std::string added_value("added value");
127 put_value = added_value;
128 status = leveldb->Put(added_key, &put_value);
129 EXPECT_TRUE(status.ok());
130
131 status = leveldb->Get(added_key, &got_value, &found);
132 EXPECT_TRUE(status.ok());
133 EXPECT_TRUE(found);
134 EXPECT_EQ(comparator.Compare(got_value, added_value), 0);
135
136 status = transaction->Get(added_key, &got_value, &found);
137 EXPECT_TRUE(status.ok());
138 EXPECT_FALSE(found);
139
140 const std::string another_key("another key");
141 const std::string another_value("another value");
142 put_value = another_value;
143 transaction->Put(another_key, &put_value);
144
145 status = transaction->Get(another_key, &got_value, &found);
146 EXPECT_TRUE(status.ok());
147 EXPECT_TRUE(found);
148 EXPECT_EQ(comparator.Compare(got_value, another_value), 0);
149 }
150
TEST(LevelDBDatabaseTest,TransactionIterator)151 TEST(LevelDBDatabaseTest, TransactionIterator) {
152 base::ScopedTempDir temp_directory;
153 ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
154
155 const std::string key1("key1");
156 const std::string value1("value1");
157 const std::string key2("key2");
158 const std::string value2("value2");
159 std::string put_value;
160 SimpleComparator comparator;
161
162 scoped_ptr<LevelDBDatabase> leveldb;
163 LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
164 EXPECT_TRUE(leveldb);
165
166 put_value = value1;
167 leveldb::Status s = leveldb->Put(key1, &put_value);
168 EXPECT_TRUE(s.ok());
169 put_value = value2;
170 s = leveldb->Put(key2, &put_value);
171 EXPECT_TRUE(s.ok());
172
173 scoped_refptr<LevelDBTransaction> transaction =
174 new LevelDBTransaction(leveldb.get());
175
176 s = leveldb->Remove(key2);
177 EXPECT_TRUE(s.ok());
178
179 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
180
181 it->Seek(std::string());
182
183 EXPECT_TRUE(it->IsValid());
184 EXPECT_EQ(comparator.Compare(it->Key(), key1), 0);
185 EXPECT_EQ(comparator.Compare(it->Value(), value1), 0);
186
187 it->Next();
188
189 EXPECT_TRUE(it->IsValid());
190 EXPECT_EQ(comparator.Compare(it->Key(), key2), 0);
191 EXPECT_EQ(comparator.Compare(it->Value(), value2), 0);
192
193 it->Next();
194
195 EXPECT_FALSE(it->IsValid());
196 }
197
TEST(LevelDBDatabaseTest,TransactionCommitTest)198 TEST(LevelDBDatabaseTest, TransactionCommitTest) {
199 base::ScopedTempDir temp_directory;
200 ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
201
202 const std::string key1("key1");
203 const std::string key2("key2");
204 const std::string value1("value1");
205 const std::string value2("value2");
206 const std::string value3("value3");
207
208 std::string put_value;
209 std::string got_value;
210 SimpleComparator comparator;
211 bool found;
212
213 scoped_ptr<LevelDBDatabase> leveldb;
214 LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
215 EXPECT_TRUE(leveldb);
216
217 scoped_refptr<LevelDBTransaction> transaction =
218 new LevelDBTransaction(leveldb.get());
219
220 put_value = value1;
221 transaction->Put(key1, &put_value);
222
223 put_value = value2;
224 transaction->Put(key2, &put_value);
225
226 put_value = value3;
227 transaction->Put(key2, &put_value);
228
229 leveldb::Status status = transaction->Commit();
230 EXPECT_TRUE(status.ok());
231
232 status = leveldb->Get(key1, &got_value, &found);
233 EXPECT_TRUE(status.ok());
234 EXPECT_TRUE(found);
235 EXPECT_EQ(value1, got_value);
236
237 status = leveldb->Get(key2, &got_value, &found);
238 EXPECT_TRUE(status.ok());
239 EXPECT_TRUE(found);
240 EXPECT_EQ(value3, got_value);
241 }
242
TEST(LevelDB,Locking)243 TEST(LevelDB, Locking) {
244 base::ScopedTempDir temp_directory;
245 ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
246
247 leveldb::Env* env = leveldb::IDBEnv();
248 base::FilePath file = temp_directory.path().AppendASCII("LOCK");
249 leveldb::FileLock* lock;
250 leveldb::Status status = env->LockFile(file.AsUTF8Unsafe(), &lock);
251 EXPECT_TRUE(status.ok());
252
253 status = env->UnlockFile(lock);
254 EXPECT_TRUE(status.ok());
255
256 status = env->LockFile(file.AsUTF8Unsafe(), &lock);
257 EXPECT_TRUE(status.ok());
258
259 leveldb::FileLock* lock2;
260 status = env->LockFile(file.AsUTF8Unsafe(), &lock2);
261 EXPECT_FALSE(status.ok());
262
263 status = env->UnlockFile(lock);
264 EXPECT_TRUE(status.ok());
265 }
266
267 } // namespace content
268