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: 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 36 } // namespace 37 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 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 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 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 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