Home | History | Annotate | Download | only in leveldb
      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