• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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