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.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