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 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 TEST(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 90 TEST(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 154 TEST(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 202 TEST(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 248 TEST(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