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